)]}'
{"doc/source/auth-totp.rst":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"332c938e030c44a0d01542068a7847803db38c1c","unresolved":false,"context_lines":[{"line_number":23,"context_line":"Keystone and a TOTP device (i.e. Google Authenticator)."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"TOTP uses a base32 encoded string for the secret."},{"line_number":26,"context_line":"The following python code can be used to Generate a TOTP secret:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":".. code-block:: python"},{"line_number":29,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"dae33548_45b19146","line":26,"updated":"2016-02-17 17:10:52.000000000","message":"generate*","commit_id":"05ffc8e3c06112eece53e3c81084b47a1b2ba472"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"5d3c113335e0a33fe98d339fbcf5dad0eb68f851","unresolved":false,"context_lines":[{"line_number":23,"context_line":"Keystone and a TOTP device (i.e. Google Authenticator)."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"TOTP uses a base32 encoded string for the secret."},{"line_number":26,"context_line":"The following python code can be used to Generate a TOTP secret:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":".. code-block:: python"},{"line_number":29,"context_line":""}],"source_content_type":"text/x-rst","patch_set":10,"id":"dae33548_404dff3c","line":26,"in_reply_to":"dae33548_45b19146","updated":"2016-02-17 17:30:18.000000000","message":"Done","commit_id":"05ffc8e3c06112eece53e3c81084b47a1b2ba472"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"332c938e030c44a0d01542068a7847803db38c1c","unresolved":false,"context_lines":[{"line_number":38,"context_line":"This generated secret can then be used to add new \u0027totp\u0027 credentials to a"},{"line_number":39,"context_line":"specific user."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"POST /v3/credentials"},{"line_number":42,"context_line":"--------------------"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"Create \u0027totp\u0027 credentials for user:"}],"source_content_type":"text/x-rst","patch_set":10,"id":"dae33548_e57ee568","line":41,"updated":"2016-02-17 17:10:52.000000000","message":"\"Create a TOTP credential\"","commit_id":"05ffc8e3c06112eece53e3c81084b47a1b2ba472"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"5d3c113335e0a33fe98d339fbcf5dad0eb68f851","unresolved":false,"context_lines":[{"line_number":38,"context_line":"This generated secret can then be used to add new \u0027totp\u0027 credentials to a"},{"line_number":39,"context_line":"specific user."},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"POST /v3/credentials"},{"line_number":42,"context_line":"--------------------"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"Create \u0027totp\u0027 credentials for user:"}],"source_content_type":"text/x-rst","patch_set":10,"id":"dae33548_605003d5","line":41,"in_reply_to":"dae33548_e57ee568","updated":"2016-02-17 17:30:18.000000000","message":"Done","commit_id":"05ffc8e3c06112eece53e3c81084b47a1b2ba472"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"332c938e030c44a0d01542068a7847803db38c1c","unresolved":false,"context_lines":[{"line_number":65,"context_line":""},{"line_number":66,"context_line":"On a device install Google Authenticator and inside the app click on \u0027Set up"},{"line_number":67,"context_line":"account\u0027 and then click on \u0027Enter provided key\u0027.  In the input fields enter"},{"line_number":68,"context_line":"account name and secret.  Optionally a qr code can be generated programatically"},{"line_number":69,"context_line":"to avoid having to type the information."},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"QR code"}],"source_content_type":"text/x-rst","patch_set":10,"id":"dae33548_85e55939","line":68,"updated":"2016-02-17 17:10:52.000000000","message":"QR","commit_id":"05ffc8e3c06112eece53e3c81084b47a1b2ba472"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"5d3c113335e0a33fe98d339fbcf5dad0eb68f851","unresolved":false,"context_lines":[{"line_number":65,"context_line":""},{"line_number":66,"context_line":"On a device install Google Authenticator and inside the app click on \u0027Set up"},{"line_number":67,"context_line":"account\u0027 and then click on \u0027Enter provided key\u0027.  In the input fields enter"},{"line_number":68,"context_line":"account name and secret.  Optionally a qr code can be generated programatically"},{"line_number":69,"context_line":"to avoid having to type the information."},{"line_number":70,"context_line":""},{"line_number":71,"context_line":"QR code"}],"source_content_type":"text/x-rst","patch_set":10,"id":"dae33548_2071db76","line":68,"in_reply_to":"dae33548_85e55939","updated":"2016-02-17 17:30:18.000000000","message":"Done","commit_id":"05ffc8e3c06112eece53e3c81084b47a1b2ba472"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"dae33548_88d3925f","updated":"2016-02-18 06:36:29.000000000","message":"add this doc to the index of else no one will be able to find it: https://github.com/openstack/keystone/blob/master/doc/source/index.rst","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"dae33548_6f46027c","in_reply_to":"dae33548_88d3925f","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":20,"context_line":"----------------"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"For a user to have access to TOTP, he must have configured TOTP credentials in"},{"line_number":23,"context_line":"Keystone and a TOTP device (i.e. Google Authenticator)."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"TOTP uses a base32 encoded string for the secret."},{"line_number":26,"context_line":"The following python code can be used to generate a TOTP secret:"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_0876626f","line":23,"range":{"start_line":23,"start_character":33,"end_line":23,"end_character":53},"updated":"2016-02-18 06:36:29.000000000","message":"maybe make this link to: http://www.google.com/2step","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":20,"context_line":"----------------"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"For a user to have access to TOTP, he must have configured TOTP credentials in"},{"line_number":23,"context_line":"Keystone and a TOTP device (i.e. Google Authenticator)."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"TOTP uses a base32 encoded string for the secret."},{"line_number":26,"context_line":"The following python code can be used to generate a TOTP secret:"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_ca6bbcb5","line":23,"range":{"start_line":23,"start_character":33,"end_line":23,"end_character":53},"in_reply_to":"dae33548_0876626f","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":23,"context_line":"Keystone and a TOTP device (i.e. Google Authenticator)."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"TOTP uses a base32 encoded string for the secret."},{"line_number":26,"context_line":"The following python code can be used to generate a TOTP secret:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":".. code-block:: python"},{"line_number":29,"context_line":""}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_a884960a","line":26,"range":{"start_line":26,"start_character":0,"end_line":26,"end_character":64},"updated":"2016-02-18 06:36:29.000000000","message":"nit: use the space on the previous line","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":23,"context_line":"Keystone and a TOTP device (i.e. Google Authenticator)."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"TOTP uses a base32 encoded string for the secret."},{"line_number":26,"context_line":"The following python code can be used to generate a TOTP secret:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":".. code-block:: python"},{"line_number":29,"context_line":""}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_cae0dc2b","line":26,"range":{"start_line":26,"start_character":0,"end_line":26,"end_character":64},"in_reply_to":"dae33548_a884960a","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"8497798df9886cb27520c3ed1cb3dce91cc7d451","unresolved":false,"context_lines":[{"line_number":24,"context_line":""},{"line_number":25,"context_line":"TOTP uses a base32 encoded string for the secret."},{"line_number":26,"context_line":"The following python code can be used to generate a TOTP secret:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":".. code-block:: python"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"    import base64"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_1524bf5b","line":27,"updated":"2016-02-18 06:07:41.000000000","message":"No need to write code. Just use openstack CLI after this patch lands.\n\nhttps://review.openstack.org/#/c/279854/\n\nFor example:\n\n    openstack --os-auth-url http://localhost:35357/v3 --os-username admin --os-password secrete --os-user-domain-id default --os-project-name admin --os-project-domain-id default --os-identity-api-version 3 credential create --type totp --include-google-authenticator-provisioning-url demo test_credential_blah_blah\n\nOnce the credential is created in Keystone. You can then provision your Google Authenticator by copy-n-pasting the provisioning URL to your browser to pick up your QR code. Then scan the QR code with your phone.","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"eab761972eccc9e0885c90522ec814bb146a01ee","unresolved":false,"context_lines":[{"line_number":24,"context_line":""},{"line_number":25,"context_line":"TOTP uses a base32 encoded string for the secret."},{"line_number":26,"context_line":"The following python code can be used to generate a TOTP secret:"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":".. code-block:: python"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"    import base64"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_f5ae7b2c","line":27,"in_reply_to":"dae33548_1524bf5b","updated":"2016-02-18 06:12:34.000000000","message":"I\u0027m OK with keeping the proposed code around, it doesn\u0027t hurt. We can remove once OSC actually has support for TOTP","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":41,"context_line":"Create a TOTP credential"},{"line_number":42,"context_line":"------------------------"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"Create \u0027totp\u0027 credentials for user:"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":".. code-block:: bash"},{"line_number":47,"context_line":""}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_e8c21e84","line":44,"range":{"start_line":44,"start_character":7,"end_line":44,"end_character":13},"updated":"2016-02-18 06:36:29.000000000","message":"use backticks `` instead of single quotes, it\u0027ll emphasize that we\u0027re talking about the keystone auth concept now","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":41,"context_line":"Create a TOTP credential"},{"line_number":42,"context_line":"------------------------"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"Create \u0027totp\u0027 credentials for user:"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":".. code-block:: bash"},{"line_number":47,"context_line":""}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_0abe44fe","line":44,"range":{"start_line":44,"start_character":7,"end_line":44,"end_character":13},"in_reply_to":"dae33548_e8c21e84","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":91,"context_line":"entry in the application."},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"-----------------"},{"line_number":94,"context_line":"Authenticate TOTP"},{"line_number":95,"context_line":"-----------------"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"Google Authenticator will generate a 6 digit pin (passcode) every few seconds."}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_481a2a18","line":94,"range":{"start_line":94,"start_character":0,"end_line":94,"end_character":17},"updated":"2016-02-18 06:36:29.000000000","message":"Authenticate with TOTP","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":94,"context_line":"Authenticate TOTP"},{"line_number":95,"context_line":"-----------------"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"Google Authenticator will generate a 6 digit pin (passcode) every few seconds."},{"line_number":98,"context_line":"Use the passcode to authenticate a user using the totp method."},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"Tokens"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_c8aaba84","line":97,"range":{"start_line":97,"start_character":45,"end_line":97,"end_character":48},"updated":"2016-02-18 06:36:29.000000000","message":"PIN*","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":94,"context_line":"Authenticate TOTP"},{"line_number":95,"context_line":"-----------------"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"Google Authenticator will generate a 6 digit pin (passcode) every few seconds."},{"line_number":98,"context_line":"Use the passcode to authenticate a user using the totp method."},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"Tokens"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_ea4fa031","line":97,"range":{"start_line":97,"start_character":45,"end_line":97,"end_character":48},"in_reply_to":"dae33548_c8aaba84","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":95,"context_line":"-----------------"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"Google Authenticator will generate a 6 digit pin (passcode) every few seconds."},{"line_number":98,"context_line":"Use the passcode to authenticate a user using the totp method."},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"Tokens"},{"line_number":101,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_28c36658","line":98,"range":{"start_line":98,"start_character":0,"end_line":98,"end_character":62},"updated":"2016-02-18 06:36:29.000000000","message":"Use the passcode and your user ID to authenticate using the ``totp`` method.","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":95,"context_line":"-----------------"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"Google Authenticator will generate a 6 digit pin (passcode) every few seconds."},{"line_number":98,"context_line":"Use the passcode to authenticate a user using the totp method."},{"line_number":99,"context_line":""},{"line_number":100,"context_line":"Tokens"},{"line_number":101,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_2a0b48d7","line":98,"range":{"start_line":98,"start_character":0,"end_line":98,"end_character":62},"in_reply_to":"dae33548_28c36658","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"8497798df9886cb27520c3ed1cb3dce91cc7d451","unresolved":false,"context_lines":[{"line_number":104,"context_line":"-------------"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"Get a token with default scope (may be unscoped) using totp:"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":".. code-block:: bash"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    USER_ID\u003db7793000f8d84c79af4e215e9da78654"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_75954b31","line":107,"updated":"2016-02-18 06:07:41.000000000","message":"You can also use openstack CLI to test this after the keystoneauth patch lands.\n\nhttps://review.openstack.org/#/c/281086/\n\nFor example:\n\n  openstack --os-auth-type v3totp --os-auth-url http://localhost:35357/v3 --os-username admin --os-passcode 123456 --os-user-domain-id default --os-project-name admin --os-project-domain-id default --os-identity-api-version 3 token issue","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"eab761972eccc9e0885c90522ec814bb146a01ee","unresolved":false,"context_lines":[{"line_number":104,"context_line":"-------------"},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"Get a token with default scope (may be unscoped) using totp:"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":".. code-block:: bash"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    USER_ID\u003db7793000f8d84c79af4e215e9da78654"}],"source_content_type":"text/x-rst","patch_set":12,"id":"dae33548_95660f28","line":107,"in_reply_to":"dae33548_75954b31","updated":"2016-02-18 06:12:34.000000000","message":"I\u0027m OK with keeping the proposed code around, it doesn\u0027t hurt. We can remove once OSC actually has support for TOTP","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"03dfac2b8e29f4899e916bc1a139204f42f02536","unresolved":false,"context_lines":[{"line_number":19,"context_line":"Configuring TOTP"},{"line_number":20,"context_line":"----------------"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"For a user to have access to TOTP, he must have configured TOTP credentials in"},{"line_number":23,"context_line":"Keystone and a TOTP device (i.e. `Google Authenticator`_)."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":".. _Google Authenticator: http://www.google.com/2step"}],"source_content_type":"text/x-rst","patch_set":14,"id":"dae33548_010e0ae5","line":22,"updated":"2016-02-18 23:26:29.000000000","message":"Should mention totp needs to be enabled in keystone.conf:\n\n[auth]\nmethods \u003d external,password,token,oauth1,totp","commit_id":"ef6f28504a9ed74b8622c45f9a6793d779e47650"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"4dff64d1d1b1ea6043226e4b779856353cf345b2","unresolved":false,"context_lines":[{"line_number":19,"context_line":"Configuring TOTP"},{"line_number":20,"context_line":"----------------"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"For a user to have access to TOTP, he must have configured TOTP credentials in"},{"line_number":23,"context_line":"Keystone and a TOTP device (i.e. `Google Authenticator`_)."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":".. _Google Authenticator: http://www.google.com/2step"}],"source_content_type":"text/x-rst","patch_set":14,"id":"dae33548_81485ace","line":22,"in_reply_to":"dae33548_010e0ae5","updated":"2016-02-18 23:36:42.000000000","message":"Done","commit_id":"ef6f28504a9ed74b8622c45f9a6793d779e47650"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"d4c550f57494d98f7ff04125f101f4df6d8c13ca","unresolved":false,"context_lines":[{"line_number":38,"context_line":".. code-block:: python"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    import base64"},{"line_number":41,"context_line":"    message \u003d \u00271234567890123456\u0027"},{"line_number":42,"context_line":"    print base64.b32encode(message).rstrip(\u0027\u003d\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"Example output::"}],"source_content_type":"text/x-rst","patch_set":15,"id":"dae33548_aab9f3cd","line":41,"range":{"start_line":41,"start_character":31,"end_line":41,"end_character":32},"updated":"2016-02-19 01:20:51.000000000","message":"Worth mentioning that secret must be at least 148 bits (16 bytes).","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"4c2d331627751b6662f5ce307c3c6ff877743551","unresolved":false,"context_lines":[{"line_number":38,"context_line":".. code-block:: python"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    import base64"},{"line_number":41,"context_line":"    message \u003d \u00271234567890123456\u0027"},{"line_number":42,"context_line":"    print base64.b32encode(message).rstrip(\u0027\u003d\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":"Example output::"}],"source_content_type":"text/x-rst","patch_set":15,"id":"dae33548_c0bff35e","line":41,"range":{"start_line":41,"start_character":31,"end_line":41,"end_character":32},"in_reply_to":"dae33548_aab9f3cd","updated":"2016-02-19 05:51:05.000000000","message":"Done","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"d4c550f57494d98f7ff04125f101f4df6d8c13ca","unresolved":false,"context_lines":[{"line_number":56,"context_line":".. code-block:: bash"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    USER_ID\u003db7793000f8d84c79af4e215e9da78654"},{"line_number":59,"context_line":"    SECRET\u003dGEZDGNBVGY3TQOJQGEZDGNBVGY"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"    curl -i \\"},{"line_number":62,"context_line":"      -H \"Content-Type: application/json\" \\"}],"source_content_type":"text/x-rst","patch_set":15,"id":"dae33548_eab3fbe7","line":59,"range":{"start_line":59,"start_character":11,"end_line":59,"end_character":37},"updated":"2016-02-19 01:20:51.000000000","message":"base-32 encoded secret","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"d4c550f57494d98f7ff04125f101f4df6d8c13ca","unresolved":false,"context_lines":[{"line_number":85,"context_line":""},{"line_number":86,"context_line":".. code-block:: python"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"    import qrcode"},{"line_number":89,"context_line":""},{"line_number":90,"context_line":"    secret\u003d\u0027GEZDGNBVGY3TQOJQGEZDGNBVGY\u0027"},{"line_number":91,"context_line":"    uri \u003d \u0027otpauth://totp/{name}?secret\u003d{secret}\u0026issuer\u003d{issuer}\u0027.format("}],"source_content_type":"text/x-rst","patch_set":15,"id":"dae33548_8ac34f38","line":88,"range":{"start_line":88,"start_character":11,"end_line":88,"end_character":17},"updated":"2016-02-19 01:20:51.000000000","message":"Nice! You can also use the google url.","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"}],"keystone/auth/plugins/core.py":[{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"4dd6a64d722d4db6b090930fb19ccd091e60cdbb","unresolved":false,"context_lines":[{"line_number":111,"context_line":"    def __init__(self):"},{"line_number":112,"context_line":"        self.user_id \u003d None"},{"line_number":113,"context_line":"        self.password \u003d None"},{"line_number":114,"context_line":"        self.passcode \u003d None"},{"line_number":115,"context_line":"        self.user_ref \u003d None"},{"line_number":116,"context_line":"        self.METHOD_NAME \u003d None"},{"line_number":117,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_2b9fda60","line":114,"range":{"start_line":114,"start_character":13,"end_line":114,"end_character":21},"updated":"2016-02-09 20:01:39.000000000","message":"suggest refactor UserInfo into BaseUserInfo, PasswordUserInfo, and TOTPUserInfo. They are really different payloads with some commonalities.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":111,"context_line":"    def __init__(self):"},{"line_number":112,"context_line":"        self.user_id \u003d None"},{"line_number":113,"context_line":"        self.password \u003d None"},{"line_number":114,"context_line":"        self.passcode \u003d None"},{"line_number":115,"context_line":"        self.user_ref \u003d None"},{"line_number":116,"context_line":"        self.METHOD_NAME \u003d None"},{"line_number":117,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_972d56aa","line":114,"range":{"start_line":114,"start_character":13,"end_line":114,"end_character":21},"in_reply_to":"3a57f1b5_2b9fda60","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"1cbd47fa0c9d71bd0aa59042518e3050bdcfe336","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"@dependency.requires(\u0027identity_api\u0027, \u0027resource_api\u0027)"},{"line_number":102,"context_line":"class BaseUserInfo(object):"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @staticmethod"},{"line_number":105,"context_line":"    def create(auth_payload, method_name):"}],"source_content_type":"text/x-python","patch_set":6,"id":"3a57f1b5_e29e0a62","line":102,"updated":"2016-02-12 18:16:15.000000000","message":"This is a public interface. You can\u0027t just \"Rename\" it without having at least a stub to support things that rely on it.","commit_id":"244a6c8d0bee75e0a3074425b683da2a18ca26b4"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"555ea803ebc8f83f23715f9f27b8f09cbf5ddebf","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"@dependency.requires(\u0027identity_api\u0027, \u0027resource_api\u0027)"},{"line_number":102,"context_line":"class BaseUserInfo(object):"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @staticmethod"},{"line_number":105,"context_line":"    def create(auth_payload, method_name):"}],"source_content_type":"text/x-python","patch_set":6,"id":"dae33548_1a0d9f3e","line":102,"in_reply_to":"3a57f1b5_e29e0a62","updated":"2016-02-15 18:39:00.000000000","message":"Done","commit_id":"244a6c8d0bee75e0a3074425b683da2a18ca26b4"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"1cf5e9a2e52048fe508d0e9351041f07cd0a5ba4","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"@dependency.requires(\u0027identity_api\u0027, \u0027resource_api\u0027)"},{"line_number":102,"context_line":"class BaseUserInfo(object):"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @staticmethod"},{"line_number":105,"context_line":"    def create(auth_payload, method_name):"}],"source_content_type":"text/x-python","patch_set":6,"id":"dae33548_3accec34","line":102,"in_reply_to":"3a57f1b5_e29e0a62","updated":"2016-02-15 15:25:17.000000000","message":"Suggest not changing this.","commit_id":"244a6c8d0bee75e0a3074425b683da2a18ca26b4"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"555ea803ebc8f83f23715f9f27b8f09cbf5ddebf","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"@dependency.requires(\u0027identity_api\u0027, \u0027resource_api\u0027)"},{"line_number":102,"context_line":"class BaseUserInfo(object):"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @staticmethod"},{"line_number":105,"context_line":"    def create(auth_payload, method_name):"}],"source_content_type":"text/x-python","patch_set":6,"id":"dae33548_5a07271c","line":102,"in_reply_to":"dae33548_3accec34","updated":"2016-02-15 18:39:00.000000000","message":"Done","commit_id":"244a6c8d0bee75e0a3074425b683da2a18ca26b4"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":102,"context_line":"class BaseUserInfo(object):"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @staticmethod"},{"line_number":105,"context_line":"    def create(auth_payload, method_name):"},{"line_number":106,"context_line":"        raise exception.NotImplemented()  # pragma: no cover"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"    def __init__(self):"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_b0d9ca59","line":105,"updated":"2016-02-17 15:45:25.000000000","message":"If the original implementation was turned into a classmethod then the code wouldn\u0027t have to be copied to each subclass.","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":102,"context_line":"class BaseUserInfo(object):"},{"line_number":103,"context_line":""},{"line_number":104,"context_line":"    @staticmethod"},{"line_number":105,"context_line":"    def create(auth_payload, method_name):"},{"line_number":106,"context_line":"        raise exception.NotImplemented()  # pragma: no cover"},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"    def __init__(self):"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_aa46614c","line":105,"in_reply_to":"dae33548_b0d9ca59","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":213,"context_line":""},{"line_number":214,"context_line":"    def __init__(self):"},{"line_number":215,"context_line":"        super(TOTPUserInfo, self).__init__()"},{"line_number":216,"context_line":"        self.passcode \u003d None"},{"line_number":217,"context_line":""},{"line_number":218,"context_line":"    def _validate_and_normalize_auth_data(self, auth_payload):"},{"line_number":219,"context_line":"        super(TOTPUserInfo, self)._validate_and_normalize_auth_data("}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_90748636","line":216,"updated":"2016-02-17 15:45:25.000000000","message":"Where is this actually used?","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":185,"context_line":"        self.domain_id \u003d domain_ref[\u0027id\u0027]"},{"line_number":186,"context_line":""},{"line_number":187,"context_line":""},{"line_number":188,"context_line":"class UserAuthInfo(BaseUserInfo):"},{"line_number":189,"context_line":""},{"line_number":190,"context_line":"    def __init__(self):"},{"line_number":191,"context_line":"        super(UserAuthInfo, self).__init__()"},{"line_number":192,"context_line":"        self.password \u003d None"},{"line_number":193,"context_line":""},{"line_number":194,"context_line":"    def _validate_and_normalize_auth_data(self, auth_payload):"},{"line_number":195,"context_line":"        super(UserAuthInfo, self)._validate_and_normalize_auth_data("},{"line_number":196,"context_line":"            auth_payload)"},{"line_number":197,"context_line":"        user_info \u003d auth_payload[\u0027user\u0027]"},{"line_number":198,"context_line":"        self.password \u003d user_info.get(\u0027password\u0027)"},{"line_number":199,"context_line":""},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"class TOTPUserInfo(BaseUserInfo):"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"    def __init__(self):"},{"line_number":204,"context_line":"        super(TOTPUserInfo, self).__init__()"},{"line_number":205,"context_line":"        self.passcode \u003d None"},{"line_number":206,"context_line":""},{"line_number":207,"context_line":"    def _validate_and_normalize_auth_data(self, auth_payload):"},{"line_number":208,"context_line":"        super(TOTPUserInfo, self)._validate_and_normalize_auth_data("},{"line_number":209,"context_line":"            auth_payload)"},{"line_number":210,"context_line":"        user_info \u003d auth_payload[\u0027user\u0027]"},{"line_number":211,"context_line":"        self.passcode \u003d user_info.get(\u0027passcode\u0027)"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_4876aa3e","line":211,"range":{"start_line":188,"start_character":0,"end_line":211,"end_character":49},"updated":"2016-02-18 06:36:29.000000000","message":"nice","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"25677ec3d01af7307595ba5e695a3cac14b341f5","unresolved":false,"context_lines":[{"line_number":198,"context_line":"        self.password \u003d user_info.get(\u0027password\u0027)"},{"line_number":199,"context_line":""},{"line_number":200,"context_line":""},{"line_number":201,"context_line":"class TOTPUserInfo(BaseUserInfo):"},{"line_number":202,"context_line":""},{"line_number":203,"context_line":"    def __init__(self):"},{"line_number":204,"context_line":"        super(TOTPUserInfo, self).__init__()"}],"source_content_type":"text/x-python","patch_set":15,"id":"dae33548_473e622a","line":201,"updated":"2016-02-19 00:48:00.000000000","message":"This seems wrong to me, but can be cleaned up later. I think it\u0027s a little crappy to encode classes to specifically make the AuthInfo in plugins.core rather than within the plugin class itself. \n\nthat would be a lot more rearchitecting than is needed here though.","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"}],"keystone/auth/plugins/totp.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"c3d99fafc624bb8d92b191ed23d89f25c60d93a9","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2013 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a5de9d1_82d5abe5","line":1,"range":{"start_line":1,"start_character":0,"end_line":1,"end_character":37},"updated":"2016-02-01 22:12:12.000000000","message":"wrong copyright","commit_id":"1139da65d9ddcb94a1aa56aeca7d7f3c875f5c17"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"3d5fa7d55aa9107c579498ed6590a9212aaef1a4","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2013 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a5de9d1_333ad6e8","line":1,"range":{"start_line":1,"start_character":0,"end_line":1,"end_character":37},"in_reply_to":"7a5de9d1_82d5abe5","updated":"2016-02-02 19:41:18.000000000","message":"Done","commit_id":"1139da65d9ddcb94a1aa56aeca7d7f3c875f5c17"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"c3d99fafc624bb8d92b191ed23d89f25c60d93a9","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"from keystone import auth"},{"line_number":20,"context_line":"from keystone.auth import plugins as auth_plugins"},{"line_number":21,"context_line":"from keystone.auth.plugins import UserAuthInfo"},{"line_number":22,"context_line":"from keystone.common import dependency"},{"line_number":23,"context_line":"from keystone.common import driver_hints"},{"line_number":24,"context_line":"from keystone import exception"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a5de9d1_a2fb0778","line":21,"range":{"start_line":21,"start_character":0,"end_line":21,"end_character":46},"updated":"2016-02-01 22:12:12.000000000","message":"use module level imports only, not class level\n\nalso, it\u0027s not used since you are using auth_plugins","commit_id":"1139da65d9ddcb94a1aa56aeca7d7f3c875f5c17"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"3d5fa7d55aa9107c579498ed6590a9212aaef1a4","unresolved":false,"context_lines":[{"line_number":18,"context_line":""},{"line_number":19,"context_line":"from keystone import auth"},{"line_number":20,"context_line":"from keystone.auth import plugins as auth_plugins"},{"line_number":21,"context_line":"from keystone.auth.plugins import UserAuthInfo"},{"line_number":22,"context_line":"from keystone.common import dependency"},{"line_number":23,"context_line":"from keystone.common import driver_hints"},{"line_number":24,"context_line":"from keystone import exception"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a5de9d1_533f52d6","line":21,"range":{"start_line":21,"start_character":0,"end_line":21,"end_character":46},"in_reply_to":"7a5de9d1_a2fb0778","updated":"2016-02-02 19:41:18.000000000","message":"Done","commit_id":"1139da65d9ddcb94a1aa56aeca7d7f3c875f5c17"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3d2a28c5880351361821298d5fbe97bdd554b750","unresolved":false,"context_lines":[{"line_number":30,"context_line":""},{"line_number":31,"context_line":"@dependency.requires(\u0027credential_api\u0027)"},{"line_number":32,"context_line":"class TOTP(auth.AuthMethodHandler):"},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    def authenticate(self, context, auth_payload, auth_context):"},{"line_number":35,"context_line":"        \"\"\"Try to authenticate using TOTP\"\"\""},{"line_number":36,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7a5de9d1_677de1e6","line":33,"updated":"2016-02-02 22:07:08.000000000","message":"this line can be removed - \n\nhttp://logs.openstack.org/01/274901/2/check/gate-keystone-linters/ee75f02/console.html","commit_id":"2b7cbd2926f610c87df00daae805f67d153e0604"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3d2a28c5880351361821298d5fbe97bdd554b750","unresolved":false,"context_lines":[{"line_number":36,"context_line":""},{"line_number":37,"context_line":"        try:"},{"line_number":38,"context_line":"            user_info \u003d auth_plugins.UserAuthInfo.create(auth_payload,"},{"line_number":39,"context_line":"                METHOD_NAME)"},{"line_number":40,"context_line":"            auth_passcode \u003d auth_payload.get(\u0027user\u0027).get(\u0027passcode\u0027)"},{"line_number":41,"context_line":"            user_id \u003d user_info.user_id"},{"line_number":42,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7a5de9d1_8776dd04","line":39,"updated":"2016-02-02 22:07:08.000000000","message":"This can be indented under auth_payload, like: \n\n    auth_payload,\n    METHOD_NAME)\n\nhttp://logs.openstack.org/01/274901/2/check/gate-keystone-linters/ee75f02/console.html","commit_id":"2b7cbd2926f610c87df00daae805f67d153e0604"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3d2a28c5880351361821298d5fbe97bdd554b750","unresolved":false,"context_lines":[{"line_number":54,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":55,"context_line":"                        valid_passcode \u003d True"},{"line_number":56,"context_line":"                        continue"},{"line_number":57,"context_line":"                except:"},{"line_number":58,"context_line":"                    pass"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"            if not valid_passcode:"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a5de9d1_275e0977","line":57,"updated":"2016-02-02 22:07:08.000000000","message":"We have to attempt to catch something here.","commit_id":"2b7cbd2926f610c87df00daae805f67d153e0604"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3d2a28c5880351361821298d5fbe97bdd554b750","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            msg \u003d _(\u0027Invalid username or passcode\u0027)"},{"line_number":66,"context_line":"            raise exception.Unauthorized(msg)"},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        #auth_context[\u0027user_id\u0027] \u003d user_info.user_id"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a5de9d1_874d7dc6","line":68,"updated":"2016-02-02 22:07:08.000000000","message":"we could probably remove this.","commit_id":"2b7cbd2926f610c87df00daae805f67d153e0604"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"0ac298739e5cc6ac1be0a99627a12a08a764df09","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from oslo_log import log"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from keystone import auth"},{"line_number":18,"context_line":"from keystone.auth import plugins as auth_plugins"},{"line_number":19,"context_line":"from keystone.common import dependency"},{"line_number":20,"context_line":"from keystone.common import driver_hints"},{"line_number":21,"context_line":"from keystone import exception"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_c7a2b54b","line":18,"range":{"start_line":18,"start_character":34,"end_line":18,"end_character":49},"updated":"2016-02-09 02:30:40.000000000","message":"no reason for the rename","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":15,"context_line":"from oslo_log import log"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from keystone import auth"},{"line_number":18,"context_line":"from keystone.auth import plugins as auth_plugins"},{"line_number":19,"context_line":"from keystone.common import dependency"},{"line_number":20,"context_line":"from keystone.common import driver_hints"},{"line_number":21,"context_line":"from keystone import exception"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_9d01f7b1","line":18,"range":{"start_line":18,"start_character":34,"end_line":18,"end_character":49},"in_reply_to":"5a5ae5dd_c7a2b54b","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"c6680bb173ec770a79a873d85c77bf00481d5cff","unresolved":false,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"METHOD_NAME \u003d \u0027totp\u0027"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"@dependency.requires(\u0027credential_api\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_7dd032f8","line":28,"updated":"2016-02-09 03:07:21.000000000","message":"Is the logger needed?","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":25,"context_line":""},{"line_number":26,"context_line":"METHOD_NAME \u003d \u0027totp\u0027"},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":29,"context_line":""},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"@dependency.requires(\u0027credential_api\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_fd1fcb05","line":28,"in_reply_to":"5a5ae5dd_7dd032f8","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"4dd6a64d722d4db6b090930fb19ccd091e60cdbb","unresolved":false,"context_lines":[{"line_number":41,"context_line":""},{"line_number":42,"context_line":"            hints \u003d driver_hints.Hints()"},{"line_number":43,"context_line":"            hints.add_filter(\u0027user_id\u0027, user_id)"},{"line_number":44,"context_line":"            hints.add_filter(\u0027type\u0027, \u0027totp\u0027)"},{"line_number":45,"context_line":"            credentials \u003d self.credential_api.list_credentials(hints\u003dhints)"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"            valid_passcode \u003d False"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_0bbbfec5","line":44,"range":{"start_line":44,"start_character":37,"end_line":44,"end_character":43},"updated":"2016-02-09 20:01:39.000000000","message":"this needs to be documented, which includes the expectation for data-at-rest protection. Otherwise, this will not pass compliance.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"4dd6a64d722d4db6b090930fb19ccd091e60cdbb","unresolved":false,"context_lines":[{"line_number":48,"context_line":"            for credential in credentials:"},{"line_number":49,"context_line":"                try:"},{"line_number":50,"context_line":"                    totp_credentials \u003d json.loads(credential[\u0027blob\u0027])"},{"line_number":51,"context_line":"                    totp_secret \u003d totp_credentials[\u0027secret\u0027]"},{"line_number":52,"context_line":"                    generated_passcode \u003d totp.get_totp_token(totp_secret)"},{"line_number":53,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":54,"context_line":"                        valid_passcode \u003d True"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_6b6dd231","line":51,"range":{"start_line":51,"start_character":34,"end_line":51,"end_character":60},"updated":"2016-02-09 20:01:39.000000000","message":"need to address the data-at-rest protection concern here. I thought we\u0027ve agreed on a configurable data encryption key in keystone.conf and use it to decrypt the secret read from the database.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":48,"context_line":"            for credential in credentials:"},{"line_number":49,"context_line":"                try:"},{"line_number":50,"context_line":"                    totp_credentials \u003d json.loads(credential[\u0027blob\u0027])"},{"line_number":51,"context_line":"                    totp_secret \u003d totp_credentials[\u0027secret\u0027]"},{"line_number":52,"context_line":"                    generated_passcode \u003d totp.get_totp_token(totp_secret)"},{"line_number":53,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":54,"context_line":"                        valid_passcode \u003d True"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_5d013f04","line":51,"range":{"start_line":51,"start_character":34,"end_line":51,"end_character":60},"in_reply_to":"3a57f1b5_6b6dd231","updated":"2016-02-11 20:05:49.000000000","message":"We had agreed to split MFA into 3 separate specs:\n\n1. totp\n2. encryption of credentials\n3. enforcement of MFA\n\nThis pull request only addresses totp.  Encryption of credentials will be done later.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"c6680bb173ec770a79a873d85c77bf00481d5cff","unresolved":false,"context_lines":[{"line_number":52,"context_line":"                    generated_passcode \u003d totp.get_totp_token(totp_secret)"},{"line_number":53,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":54,"context_line":"                        valid_passcode \u003d True"},{"line_number":55,"context_line":"                        continue"},{"line_number":56,"context_line":"                except Exception:"},{"line_number":57,"context_line":"                    pass"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_dd8606db","line":55,"updated":"2016-02-09 03:07:21.000000000","message":"You don\u0027t want a continue here, you likely want a break, it is expensive to try every credential even if the first one passes.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":52,"context_line":"                    generated_passcode \u003d totp.get_totp_token(totp_secret)"},{"line_number":53,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":54,"context_line":"                        valid_passcode \u003d True"},{"line_number":55,"context_line":"                        continue"},{"line_number":56,"context_line":"                except Exception:"},{"line_number":57,"context_line":"                    pass"},{"line_number":58,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_7d3e7b8d","line":55,"in_reply_to":"5a5ae5dd_dd8606db","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"0ac298739e5cc6ac1be0a99627a12a08a764df09","unresolved":false,"context_lines":[{"line_number":53,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":54,"context_line":"                        valid_passcode \u003d True"},{"line_number":55,"context_line":"                        continue"},{"line_number":56,"context_line":"                except Exception:"},{"line_number":57,"context_line":"                    pass"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"            if not valid_passcode:"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_67af412c","line":56,"range":{"start_line":56,"start_character":16,"end_line":56,"end_character":33},"updated":"2016-02-09 02:30:40.000000000","message":"bandit is making the gate fail here. this needs a better exception, or a #nosec comment for why this is OK","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":53,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":54,"context_line":"                        valid_passcode \u003d True"},{"line_number":55,"context_line":"                        continue"},{"line_number":56,"context_line":"                except Exception:"},{"line_number":57,"context_line":"                    pass"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"            if not valid_passcode:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_68a31bb3","line":56,"range":{"start_line":56,"start_character":16,"end_line":56,"end_character":33},"in_reply_to":"5a5ae5dd_5dee96b5","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":53,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":54,"context_line":"                        valid_passcode \u003d True"},{"line_number":55,"context_line":"                        continue"},{"line_number":56,"context_line":"                except Exception:"},{"line_number":57,"context_line":"                    pass"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"            if not valid_passcode:"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_5d97ffeb","line":56,"range":{"start_line":56,"start_character":16,"end_line":56,"end_character":33},"in_reply_to":"5a5ae5dd_67af412c","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"c6680bb173ec770a79a873d85c77bf00481d5cff","unresolved":false,"context_lines":[{"line_number":53,"context_line":"                    if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":54,"context_line":"                        valid_passcode \u003d True"},{"line_number":55,"context_line":"                        continue"},{"line_number":56,"context_line":"                except Exception:"},{"line_number":57,"context_line":"                    pass"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"            if not valid_passcode:"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_5dee96b5","line":56,"range":{"start_line":56,"start_character":16,"end_line":56,"end_character":33},"in_reply_to":"5a5ae5dd_67af412c","updated":"2016-02-09 03:07:21.000000000","message":"Please comment why you\u0027re passing on any/all exceptions.\n\nSuggest if LOG is to be used, add a debug line here? or maybe TRACE level.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"c6680bb173ec770a79a873d85c77bf00481d5cff","unresolved":false,"context_lines":[{"line_number":57,"context_line":"                    pass"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"            if not valid_passcode:"},{"line_number":60,"context_line":"                raise AssertionError()"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        except AssertionError:"},{"line_number":63,"context_line":"            # authentication failed because of invalid username or passcode"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_5d4536b1","line":60,"updated":"2016-02-09 03:07:21.000000000","message":"Why raise an assertion error just to catch it a few lines down? Just raise Unauthorized","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":57,"context_line":"                    pass"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"            if not valid_passcode:"},{"line_number":60,"context_line":"                raise AssertionError()"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"        except AssertionError:"},{"line_number":63,"context_line":"            # authentication failed because of invalid username or passcode"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_a874b335","line":60,"in_reply_to":"5a5ae5dd_5d4536b1","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"c925957bfdb7def46a6deb0fd5e3b78d557d3405","unresolved":false,"context_lines":[{"line_number":41,"context_line":"        hints \u003d driver_hints.Hints()"},{"line_number":42,"context_line":"        hints.add_filter(\u0027user_id\u0027, user_id)"},{"line_number":43,"context_line":"        hints.add_filter(\u0027type\u0027, \u0027totp\u0027)"},{"line_number":44,"context_line":"        credentials \u003d self.credential_api.list_credentials(hints\u003dhints)"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"        valid_passcode \u003d False"},{"line_number":47,"context_line":"        for credential in credentials:"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_2de3a234","line":44,"range":{"start_line":44,"start_character":8,"end_line":44,"end_character":71},"updated":"2016-02-17 14:01:16.000000000","message":"Do not pass hints. When you do list_credentials with passed hints, the manager will apply list_limit to the call. If list_limit is set to 20, then you will get back only 20 credentials. I don\u0027t think this is what you want.\n\nRead docstring of https://github.com/openstack/keystone/blob/master/keystone/common/manager.py#L33 for more information.","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"b7f19ad6434fc06a0eb29f596ebb37c0ba43f21f","unresolved":false,"context_lines":[{"line_number":41,"context_line":"        hints \u003d driver_hints.Hints()"},{"line_number":42,"context_line":"        hints.add_filter(\u0027user_id\u0027, user_id)"},{"line_number":43,"context_line":"        hints.add_filter(\u0027type\u0027, \u0027totp\u0027)"},{"line_number":44,"context_line":"        credentials \u003d self.credential_api.list_credentials(hints\u003dhints)"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"        valid_passcode \u003d False"},{"line_number":47,"context_line":"        for credential in credentials:"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_ac968aed","line":44,"range":{"start_line":44,"start_character":8,"end_line":44,"end_character":71},"in_reply_to":"dae33548_2de3a234","updated":"2016-02-17 16:31:29.000000000","message":"How can I get the credentials of type totp for a specific user without using hints?\n\nWouldn\u0027t the call return all the credentials without hints?","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":13478,"name":"Boris Bobrov","email":"b.bobrov@sap.com","username":"bbobrov"},"change_message_id":"8d6bacdc704f124335269dc97aea106efb7fc2ce","unresolved":false,"context_lines":[{"line_number":41,"context_line":"        hints \u003d driver_hints.Hints()"},{"line_number":42,"context_line":"        hints.add_filter(\u0027user_id\u0027, user_id)"},{"line_number":43,"context_line":"        hints.add_filter(\u0027type\u0027, \u0027totp\u0027)"},{"line_number":44,"context_line":"        credentials \u003d self.credential_api.list_credentials(hints\u003dhints)"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"        valid_passcode \u003d False"},{"line_number":47,"context_line":"        for credential in credentials:"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_79aecb2e","line":44,"range":{"start_line":44,"start_character":8,"end_line":44,"end_character":71},"in_reply_to":"dae33548_ac968aed","updated":"2016-02-18 14:11:02.000000000","message":"please use credential_api.list_credentials_for_user","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":37,"context_line":"        user_id \u003d user_info.user_id"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"        hints \u003d driver_hints.Hints()"},{"line_number":40,"context_line":"        hints.add_filter(\u0027user_id\u0027, user_id)"},{"line_number":41,"context_line":"        hints.add_filter(\u0027type\u0027, \u0027totp\u0027)"},{"line_number":42,"context_line":"        credentials \u003d self.credential_api.list_credentials(hints\u003dhints)"},{"line_number":43,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_c8e63ae7","line":40,"range":{"start_line":40,"start_character":36,"end_line":40,"end_character":43},"updated":"2016-02-18 06:36:29.000000000","message":"just use \"user_info.user_id\" here and remove line 37, you already use \"user_info.user_id\" directly on line 61","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":37,"context_line":"        user_id \u003d user_info.user_id"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"        hints \u003d driver_hints.Hints()"},{"line_number":40,"context_line":"        hints.add_filter(\u0027user_id\u0027, user_id)"},{"line_number":41,"context_line":"        hints.add_filter(\u0027type\u0027, \u0027totp\u0027)"},{"line_number":42,"context_line":"        credentials \u003d self.credential_api.list_credentials(hints\u003dhints)"},{"line_number":43,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_eaeb20da","line":40,"range":{"start_line":40,"start_character":36,"end_line":40,"end_character":43},"in_reply_to":"dae33548_c8e63ae7","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":49,"context_line":"                    valid_passcode \u003d True"},{"line_number":50,"context_line":"                    break"},{"line_number":51,"context_line":"            except (ValueError, KeyError):"},{"line_number":52,"context_line":"                LOG.debug(\u0027currupt TOTP credentials with id %s\u0027,"},{"line_number":53,"context_line":"                          credential[\u0027id\u0027])"},{"line_number":54,"context_line":"                pass"},{"line_number":55,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_88071281","line":52,"range":{"start_line":52,"start_character":27,"end_line":52,"end_character":34},"updated":"2016-02-18 06:36:29.000000000","message":"Corrupt*\n\nInclude user ID in the exception message too","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":49,"context_line":"                    valid_passcode \u003d True"},{"line_number":50,"context_line":"                    break"},{"line_number":51,"context_line":"            except (ValueError, KeyError):"},{"line_number":52,"context_line":"                LOG.debug(\u0027currupt TOTP credentials with id %s\u0027,"},{"line_number":53,"context_line":"                          credential[\u0027id\u0027])"},{"line_number":54,"context_line":"                pass"},{"line_number":55,"context_line":""}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_caa61cad","line":52,"range":{"start_line":52,"start_character":27,"end_line":52,"end_character":34},"in_reply_to":"dae33548_88071281","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":51,"context_line":"            except (ValueError, KeyError):"},{"line_number":52,"context_line":"                LOG.debug(\u0027currupt TOTP credentials with id %s\u0027,"},{"line_number":53,"context_line":"                          credential[\u0027id\u0027])"},{"line_number":54,"context_line":"                pass"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        if not valid_passcode:"},{"line_number":57,"context_line":"            # authentication failed because of invalid username or passcode"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_2aa7c8bd","line":54,"updated":"2016-02-18 13:37:01.000000000","message":"yuck. i missed this earlier. gone.","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        if not valid_passcode:"},{"line_number":57,"context_line":"            # authentication failed because of invalid username or passcode"},{"line_number":58,"context_line":"            msg \u003d _(\u0027Invalid username or passcode\u0027)"},{"line_number":59,"context_line":"            raise exception.Unauthorized(msg)"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        auth_context[\u0027user_id\u0027] \u003d user_info.user_id"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_082ae2da","line":58,"range":{"start_line":58,"start_character":41,"end_line":58,"end_character":49},"updated":"2016-02-18 06:36:29.000000000","message":"Want to say \"TOTP passcode\" to make it more obvious? I initially read this as password","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        if not valid_passcode:"},{"line_number":57,"context_line":"            # authentication failed because of invalid username or passcode"},{"line_number":58,"context_line":"            msg \u003d _(\u0027Invalid username or passcode\u0027)"},{"line_number":59,"context_line":"            raise exception.Unauthorized(msg)"},{"line_number":60,"context_line":""},{"line_number":61,"context_line":"        auth_context[\u0027user_id\u0027] \u003d user_info.user_id"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_0ac4843d","line":58,"range":{"start_line":58,"start_character":41,"end_line":58,"end_character":49},"in_reply_to":"dae33548_082ae2da","updated":"2016-02-18 13:37:01.000000000","message":"Done","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"60d6baadddbe8c29c0d6b84b6491758446b6ada5","unresolved":false,"context_lines":[{"line_number":56,"context_line":"        secret \u003d secret.encode(\u0027utf-8\u0027)  #"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    # NOTE(nonameentername): cryptography takes a non base32 encoded value for"},{"line_number":59,"context_line":"    # TOTP.  Add the correct padding to be able to base32 decode"},{"line_number":60,"context_line":"    if len(secret) % 8 !\u003d 0:"},{"line_number":61,"context_line":"        while len(secret) % 8 !\u003d 0:"},{"line_number":62,"context_line":"            secret \u003d secret + b\u0027\u003d\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_61571726","line":59,"range":{"start_line":59,"start_character":11,"end_line":59,"end_character":13},"updated":"2016-02-18 23:08:02.000000000","message":"nit: 2 spaces","commit_id":"5a5bad7b639fb6405d9437d7eb218d7b8d5a526b"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"5fe199ee202d335859ea324c60354aae7287f049","unresolved":false,"context_lines":[{"line_number":89,"context_line":"                    valid_passcode \u003d True"},{"line_number":90,"context_line":"                    break"},{"line_number":91,"context_line":"            except (ValueError, KeyError):"},{"line_number":92,"context_line":"                LOG.debug(\u0027currupt TOTP; credential id: %s, user id: %s\u0027,"},{"line_number":93,"context_line":"                          credential[\u0027id\u0027], user_info.user_id)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        if not valid_passcode:"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_b917a5a1","line":92,"range":{"start_line":92,"start_character":27,"end_line":92,"end_character":34},"updated":"2016-02-18 17:44:41.000000000","message":"Corrupt*","commit_id":"5a5bad7b639fb6405d9437d7eb218d7b8d5a526b"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"60d6baadddbe8c29c0d6b84b6491758446b6ada5","unresolved":false,"context_lines":[{"line_number":88,"context_line":"                if auth_passcode \u003d\u003d generated_passcode:"},{"line_number":89,"context_line":"                    valid_passcode \u003d True"},{"line_number":90,"context_line":"                    break"},{"line_number":91,"context_line":"            except (ValueError, KeyError):"},{"line_number":92,"context_line":"                LOG.debug(\u0027currupt TOTP; credential id: %s, user id: %s\u0027,"},{"line_number":93,"context_line":"                          credential[\u0027id\u0027], user_info.user_id)"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"        if not valid_passcode:"},{"line_number":96,"context_line":"            # authentication failed because of invalid username or passcode"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_c145436f","line":93,"range":{"start_line":91,"start_character":12,"end_line":93,"end_character":62},"updated":"2016-02-18 23:08:02.000000000","message":"i\u0027m not getting the purpose of those catch, what is potentially raising these errors? one of the credentials from the backend? or something from the cryptography library?","commit_id":"5a5bad7b639fb6405d9437d7eb218d7b8d5a526b"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"d4c550f57494d98f7ff04125f101f4df6d8c13ca","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    # NOTE(nonameentername): cryptography takes a non base32 encoded value for"},{"line_number":58,"context_line":"    # TOTP.  Add the correct padding to be able to base32 decode"},{"line_number":59,"context_line":"    if len(secret) % 8 !\u003d 0:"},{"line_number":60,"context_line":"        while len(secret) % 8 !\u003d 0:"},{"line_number":61,"context_line":"            secret \u003d secret + b\u0027\u003d\u0027"},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"dae33548_4ae66717","line":59,"range":{"start_line":59,"start_character":4,"end_line":59,"end_character":28},"updated":"2016-02-19 01:20:51.000000000","message":"No need for this. If the secret is already base32 encoded, it should always be a multiple of 8. Otherwise, we have a problem with the encoder or it won\u0027t properly decoded.","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"4c2d331627751b6662f5ce307c3c6ff877743551","unresolved":false,"context_lines":[{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    # NOTE(nonameentername): cryptography takes a non base32 encoded value for"},{"line_number":58,"context_line":"    # TOTP.  Add the correct padding to be able to base32 decode"},{"line_number":59,"context_line":"    if len(secret) % 8 !\u003d 0:"},{"line_number":60,"context_line":"        while len(secret) % 8 !\u003d 0:"},{"line_number":61,"context_line":"            secret \u003d secret + b\u0027\u003d\u0027"},{"line_number":62,"context_line":""}],"source_content_type":"text/x-python","patch_set":15,"id":"dae33548_6076e7d9","line":59,"range":{"start_line":59,"start_character":4,"end_line":59,"end_character":28},"in_reply_to":"dae33548_4ae66717","updated":"2016-02-19 05:51:05.000000000","message":"Done","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"d4c550f57494d98f7ff04125f101f4df6d8c13ca","unresolved":false,"context_lines":[{"line_number":86,"context_line":"                    valid_passcode \u003d True"},{"line_number":87,"context_line":"                    break"},{"line_number":88,"context_line":"            except (ValueError, KeyError):"},{"line_number":89,"context_line":"                LOG.debug(\u0027currupt TOTP; credential id: %s, user id: %s\u0027,"},{"line_number":90,"context_line":"                          credential[\u0027id\u0027], user_info.user_id)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"        if not valid_passcode:"}],"source_content_type":"text/x-python","patch_set":15,"id":"dae33548_6ac40b5f","line":89,"range":{"start_line":89,"start_character":27,"end_line":89,"end_character":34},"updated":"2016-02-19 01:20:51.000000000","message":"you mean current or corrupt? How about this?\n\n  \u0027TOTP no match; credential id: %s, user_id: %s\u0027","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"4c2d331627751b6662f5ce307c3c6ff877743551","unresolved":false,"context_lines":[{"line_number":86,"context_line":"                    valid_passcode \u003d True"},{"line_number":87,"context_line":"                    break"},{"line_number":88,"context_line":"            except (ValueError, KeyError):"},{"line_number":89,"context_line":"                LOG.debug(\u0027currupt TOTP; credential id: %s, user id: %s\u0027,"},{"line_number":90,"context_line":"                          credential[\u0027id\u0027], user_info.user_id)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"        if not valid_passcode:"}],"source_content_type":"text/x-python","patch_set":15,"id":"dae33548_20433f6e","line":89,"range":{"start_line":89,"start_character":27,"end_line":89,"end_character":34},"in_reply_to":"dae33548_6ac40b5f","updated":"2016-02-19 05:51:05.000000000","message":"Done","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"}],"keystone/common/config.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"d5a0c52ddbdc474baaaaca248ded1660160f7b7a","unresolved":false,"context_lines":[{"line_number":765,"context_line":"        cfg.StrOpt(\u0027oauth1\u0027,"},{"line_number":766,"context_line":"                   help\u003d\u0027Entrypoint for the oAuth1.0 auth plugin module in \u0027"},{"line_number":767,"context_line":"                        \u0027the keystone.auth.oauth1 namespace.\u0027),"},{"line_number":768,"context_line":"        cfg.StrOpt(\u0027totp\u0027,"},{"line_number":769,"context_line":"                   help\u003d\u0027Entrypoint for the totp auth plugin module in \u0027"},{"line_number":770,"context_line":"                        \u0027the keystone.auth.totp namespace.\u0027),"},{"line_number":771,"context_line":"    ],"},{"line_number":772,"context_line":"    \u0027tokenless_auth\u0027: ["},{"line_number":773,"context_line":"        cfg.MultiStrOpt(\u0027trusted_issuer\u0027, default\u003d[],"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a57f1b5_348015f7","line":770,"range":{"start_line":768,"start_character":8,"end_line":770,"end_character":61},"updated":"2016-02-11 20:22:34.000000000","message":"i don\u0027t think we need this, we use entrypoints in setup.cfg now.\n\ni think we can remove most of the [auth] block actually..","commit_id":"d5f23b1bcb55f57471ff583efd7b54b319db65cd"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":24,"context_line":"from keystone import exception"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"_DEFAULT_AUTH_METHODS \u003d [\u0027external\u0027, \u0027password\u0027, \u0027token\u0027, \u0027oauth1\u0027, \u0027totp\u0027]"},{"line_number":28,"context_line":"_CERTFILE \u003d \u0027/etc/keystone/ssl/certs/signing_cert.pem\u0027"},{"line_number":29,"context_line":"_KEYFILE \u003d \u0027/etc/keystone/ssl/private/signing_key.pem\u0027"},{"line_number":30,"context_line":"_SSO_CALLBACK \u003d \u0027/etc/keystone/sso_callback_template.html\u0027"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_30c93a5a","line":27,"updated":"2016-02-17 15:45:25.000000000","message":"Do we want this to be defaulted right now?","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":24,"context_line":"from keystone import exception"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":""},{"line_number":27,"context_line":"_DEFAULT_AUTH_METHODS \u003d [\u0027external\u0027, \u0027password\u0027, \u0027token\u0027, \u0027oauth1\u0027, \u0027totp\u0027]"},{"line_number":28,"context_line":"_CERTFILE \u003d \u0027/etc/keystone/ssl/certs/signing_cert.pem\u0027"},{"line_number":29,"context_line":"_KEYFILE \u003d \u0027/etc/keystone/ssl/private/signing_key.pem\u0027"},{"line_number":30,"context_line":"_SSO_CALLBACK \u003d \u0027/etc/keystone/sso_callback_template.html\u0027"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_4aa35500","line":27,"in_reply_to":"dae33548_30c93a5a","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"}],"keystone/common/totp/__init__.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":10,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":11,"context_line":"# under the License."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"from keystone.common.totp.core import *  # noqa"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_76c3ba57","line":13,"updated":"2016-02-17 15:45:25.000000000","message":"Since there is nothing really common about  the totp code (and it\u0027s not much code) I\u0027m wondering if it should just like in the keystone.auth.plugins.topt module.","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"8497798df9886cb27520c3ed1cb3dce91cc7d451","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"dae33548_f5cf9b53","line":14,"updated":"2016-02-18 06:07:41.000000000","message":"There\u0027s really no need to have common/totp. We should encapsulate everything we need in the plugin itself. By having code outside of the plugin, the plugin is no longer self-contained.","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"dae33548_f47b0bbc","line":14,"in_reply_to":"dae33548_35f7435a","updated":"2016-02-18 13:37:01.000000000","message":"Yes, I mentioned that in a prior review. ( https://review.openstack.org/#/c/274901/8/keystone/common/totp/__init__.py ) Already in my next update.","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"eab761972eccc9e0885c90522ec814bb146a01ee","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"dae33548_35f7435a","line":14,"in_reply_to":"dae33548_f5cf9b53","updated":"2016-02-18 06:12:34.000000000","message":"++","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"}],"keystone/common/totp/core.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":13,"context_line":"from cryptography.hazmat.backends import default_backend"},{"line_number":14,"context_line":"from cryptography.hazmat.primitives.hashes import SHA1"},{"line_number":15,"context_line":"from cryptography.hazmat.primitives.twofactor.totp import TOTP"},{"line_number":16,"context_line":"import time"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"\"\"\"Time-based One-time Password Algorithm (TOTP) is an algorithm that computes"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_70d622f2","line":16,"updated":"2016-02-17 15:45:25.000000000","message":"Import order is incorrect.","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":13,"context_line":"from cryptography.hazmat.backends import default_backend"},{"line_number":14,"context_line":"from cryptography.hazmat.primitives.hashes import SHA1"},{"line_number":15,"context_line":"from cryptography.hazmat.primitives.twofactor.totp import TOTP"},{"line_number":16,"context_line":"import time"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"\"\"\"Time-based One-time Password Algorithm (TOTP) is an algorithm that computes"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_cab76538","line":16,"in_reply_to":"dae33548_70d622f2","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":16,"context_line":"import time"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"\"\"\"Time-based One-time Password Algorithm (TOTP) is an algorithm that computes"},{"line_number":20,"context_line":"a one-time password from a shared secret key and the current time."},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"TOTP is an implementation of a hash-based message authentication code (HMAC)."}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_50fafe75","line":19,"updated":"2016-02-17 15:45:25.000000000","message":"This should be before the imports.","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":16,"context_line":"import time"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"\"\"\"Time-based One-time Password Algorithm (TOTP) is an algorithm that computes"},{"line_number":20,"context_line":"a one-time password from a shared secret key and the current time."},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"TOTP is an implementation of a hash-based message authentication code (HMAC)."}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_aab4a134","line":19,"in_reply_to":"dae33548_50fafe75","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"def get_totp_token(secret):"},{"line_number":31,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":34,"context_line":"    :returns: totp passcode"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_90f00693","line":31,"updated":"2016-02-17 15:45:25.000000000","message":"TOTP?","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":28,"context_line":""},{"line_number":29,"context_line":""},{"line_number":30,"context_line":"def get_totp_token(secret):"},{"line_number":31,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":34,"context_line":"    :returns: totp passcode"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_35b3d6ea","line":31,"in_reply_to":"dae33548_90f00693","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":30,"context_line":"def get_totp_token(secret):"},{"line_number":31,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":34,"context_line":"    :returns: totp passcode"},{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":"    totp \u003d TOTP(str(secret), 6, SHA1(), 30, backend\u003ddefault_backend())"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_10335663","line":33,"updated":"2016-02-17 15:45:25.000000000","message":"data type?","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":30,"context_line":"def get_totp_token(secret):"},{"line_number":31,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":34,"context_line":"    :returns: totp passcode"},{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":"    totp \u003d TOTP(str(secret), 6, SHA1(), 30, backend\u003ddefault_backend())"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_75c9de58","line":33,"in_reply_to":"dae33548_10335663","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":31,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":34,"context_line":"    :returns: totp passcode"},{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":"    totp \u003d TOTP(str(secret), 6, SHA1(), 30, backend\u003ddefault_backend())"},{"line_number":37,"context_line":"    return totp.generate(time.time())"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_100a3679","line":34,"updated":"2016-02-17 15:45:25.000000000","message":"same here","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":31,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":34,"context_line":"    :returns: totp passcode"},{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":"    totp \u003d TOTP(str(secret), 6, SHA1(), 30, backend\u003ddefault_backend())"},{"line_number":37,"context_line":"    return totp.generate(time.time())"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_d5c26a33","line":34,"in_reply_to":"dae33548_100a3679","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":34,"context_line":"    :returns: totp passcode"},{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":"    totp \u003d TOTP(str(secret), 6, SHA1(), 30, backend\u003ddefault_backend())"},{"line_number":37,"context_line":"    return totp.generate(time.time())"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_10cfd629","line":36,"updated":"2016-02-17 15:45:25.000000000","message":"Don\u0027t use \u0027str\u0027 because in Py2 it\u0027s a bytes type and in Py3 it\u0027s a text type. we need to be explicit.","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":34,"context_line":"    :returns: totp passcode"},{"line_number":35,"context_line":"    \"\"\""},{"line_number":36,"context_line":"    totp \u003d TOTP(str(secret), 6, SHA1(), 30, backend\u003ddefault_backend())"},{"line_number":37,"context_line":"    return totp.generate(time.time())"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_f5e32ed7","line":36,"in_reply_to":"dae33548_10cfd629","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":20,"context_line":"same secret key will be equal."},{"line_number":21,"context_line":"\"\"\""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"import base64"},{"line_number":24,"context_line":"import time"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"from cryptography.hazmat.backends import default_backend"},{"line_number":27,"context_line":"from cryptography.hazmat.primitives import hashes"},{"line_number":28,"context_line":"from cryptography.hazmat.primitives.twofactor import totp as crypto_totp"},{"line_number":29,"context_line":"import six"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def get_totp_token(secret):"},{"line_number":33,"context_line":"    \"\"\"Generate TOTP code."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    :param bytes secret: A base32 encoded secret for the TOTP authentication"},{"line_number":36,"context_line":"    :returns: totp passcode as bytes"},{"line_number":37,"context_line":"    \"\"\""},{"line_number":38,"context_line":"    if isinstance(secret, six.text_type):"},{"line_number":39,"context_line":"        # NOTE(dstanek): since this may be coming from the JSON stored in the"},{"line_number":40,"context_line":"        # database it may be UTF-8 encoded"},{"line_number":41,"context_line":"        secret \u003d secret.encode(\u0027utf-8\u0027)  #"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    # NOTE(nonameentername): cryptography takes a non base32 encoded value for"},{"line_number":44,"context_line":"    # TOTP.  Add the correct padding to be able to base32 decode"},{"line_number":45,"context_line":"    if len(secret) % 8 !\u003d 0:"},{"line_number":46,"context_line":"        while len(secret) % 8 !\u003d 0:"},{"line_number":47,"context_line":"            secret \u003d secret + b\u0027\u003d\u0027"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    decoded \u003d base64.b32decode(secret)"},{"line_number":50,"context_line":"    totp \u003d crypto_totp.TOTP("},{"line_number":51,"context_line":"        decoded, 6, hashes.SHA1(), 30, backend\u003ddefault_backend())"},{"line_number":52,"context_line":"    return totp.generate(time.time())"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_c808fa2a","line":52,"range":{"start_line":23,"start_character":0,"end_line":52,"end_character":37},"updated":"2016-02-18 06:36:29.000000000","message":"let;s dump all this in the TOTP auth plugin and make \"get_totp_token\" private","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":20,"context_line":"same secret key will be equal."},{"line_number":21,"context_line":"\"\"\""},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"import base64"},{"line_number":24,"context_line":"import time"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"from cryptography.hazmat.backends import default_backend"},{"line_number":27,"context_line":"from cryptography.hazmat.primitives import hashes"},{"line_number":28,"context_line":"from cryptography.hazmat.primitives.twofactor import totp as crypto_totp"},{"line_number":29,"context_line":"import six"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"def get_totp_token(secret):"},{"line_number":33,"context_line":"    \"\"\"Generate TOTP code."},{"line_number":34,"context_line":""},{"line_number":35,"context_line":"    :param bytes secret: A base32 encoded secret for the TOTP authentication"},{"line_number":36,"context_line":"    :returns: totp passcode as bytes"},{"line_number":37,"context_line":"    \"\"\""},{"line_number":38,"context_line":"    if isinstance(secret, six.text_type):"},{"line_number":39,"context_line":"        # NOTE(dstanek): since this may be coming from the JSON stored in the"},{"line_number":40,"context_line":"        # database it may be UTF-8 encoded"},{"line_number":41,"context_line":"        secret \u003d secret.encode(\u0027utf-8\u0027)  #"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    # NOTE(nonameentername): cryptography takes a non base32 encoded value for"},{"line_number":44,"context_line":"    # TOTP.  Add the correct padding to be able to base32 decode"},{"line_number":45,"context_line":"    if len(secret) % 8 !\u003d 0:"},{"line_number":46,"context_line":"        while len(secret) % 8 !\u003d 0:"},{"line_number":47,"context_line":"            secret \u003d secret + b\u0027\u003d\u0027"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"    decoded \u003d base64.b32decode(secret)"},{"line_number":50,"context_line":"    totp \u003d crypto_totp.TOTP("},{"line_number":51,"context_line":"        decoded, 6, hashes.SHA1(), 30, backend\u003ddefault_backend())"},{"line_number":52,"context_line":"    return totp.generate(time.time())"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_b45ce34b","line":52,"range":{"start_line":23,"start_character":0,"end_line":52,"end_character":37},"in_reply_to":"dae33548_c808fa2a","updated":"2016-02-18 13:37:01.000000000","message":"++","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"}],"keystone/credential/backends/sql.py":[{"author":{"_account_id":7191,"name":"Jamie Lennox","email":"jamielennox@gmail.com","username":"jamielennox"},"change_message_id":"edb538459d35e3e5f765923f328db0d0978ba0f8","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            query.delete()"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    def _get_list_limit(self):"},{"line_number":116,"context_line":"        return CONF.resource.list_limit or CONF.list_limit"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_0d2a23e8","line":116,"range":{"start_line":116,"start_character":48,"end_line":116,"end_character":58},"updated":"2016-02-09 07:36:54.000000000","message":"where\u0027s this used?","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":113,"context_line":"            query.delete()"},{"line_number":114,"context_line":""},{"line_number":115,"context_line":"    def _get_list_limit(self):"},{"line_number":116,"context_line":"        return CONF.resource.list_limit or CONF.list_limit"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_bae2b92d","line":116,"range":{"start_line":116,"start_character":48,"end_line":116,"end_character":58},"in_reply_to":"5a5ae5dd_0d2a23e8","updated":"2016-02-11 20:05:49.000000000","message":"I had to use add this to be able to add the credentials api in the auth/plugins/totp.py\n\n\u0027Credential\u0027 object has no attribute \u0027_get_list_limit\u0027\nTraceback (most recent call last):\n  File \"keystone/common/wsgi.py\", line 247, in __call__\n    result \u003d method(context, **params)\n  File \"keystone/auth/controllers.py\", line 396, in authenticate_for_token\n    self.authenticate(context, auth_info, auth_context)\n  File \"keystone/auth/controllers.py\", line 520, in authenticate\n    auth_context)\n  File \"keystone/auth/plugins/totp.py\", line 45, in authenticate\n    credentials \u003d self.credential_api.list_credentials(hints\u003dhints)\n  File \"keystone/common/manager.py\", line 58, in wrapper\n    list_limit \u003d self.driver._get_list_limit()\nAttributeError: \u0027Credential\u0027 object has no attribute \u0027_get_list_limit\u0027","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from keystone.common import driver_hints"},{"line_number":16,"context_line":"from oslo_config import cfg"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from keystone.common import sql"},{"line_number":19,"context_line":"from keystone import credential"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_10e6b6af","line":16,"updated":"2016-02-17 15:45:25.000000000","message":"Import order is incorrect","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from keystone.common import driver_hints"},{"line_number":16,"context_line":"from oslo_config import cfg"},{"line_number":17,"context_line":""},{"line_number":18,"context_line":"from keystone.common import sql"},{"line_number":19,"context_line":"from keystone import credential"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_aae2e12c","line":16,"in_reply_to":"dae33548_10e6b6af","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"03dfac2b8e29f4899e916bc1a139204f42f02536","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from oslo_config import cfg"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from keystone.common import driver_hints"},{"line_number":18,"context_line":"from keystone.common import sql"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_411f7209","line":15,"updated":"2016-02-18 23:26:29.000000000","message":"I don\u0027t think these changes are needed anymore since list_credentials(hints) was changed to list_credentials_for_user","commit_id":"ef6f28504a9ed74b8622c45f9a6793d779e47650"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"4dff64d1d1b1ea6043226e4b779856353cf345b2","unresolved":false,"context_lines":[{"line_number":12,"context_line":"# License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"# under the License."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"from oslo_config import cfg"},{"line_number":16,"context_line":""},{"line_number":17,"context_line":"from keystone.common import driver_hints"},{"line_number":18,"context_line":"from keystone.common import sql"}],"source_content_type":"text/x-python","patch_set":14,"id":"dae33548_614556b2","line":15,"in_reply_to":"dae33548_411f7209","updated":"2016-02-18 23:36:42.000000000","message":"Done","commit_id":"ef6f28504a9ed74b8622c45f9a6793d779e47650"}],"keystone/tests/common/auth.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        password_data[\u0027user\u0027][\u0027password\u0027] \u003d password"},{"line_number":63,"context_line":"        return password_data"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def _build_totp_auth(self, user_id\u003dNone, username\u003dNone,"},{"line_number":66,"context_line":"                         user_domain_id\u003dNone, user_domain_name\u003dNone,"},{"line_number":67,"context_line":"                         passcode\u003dNone):"},{"line_number":68,"context_line":"        totp_data \u003d {\u0027user\u0027: {}}"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_d04bae85","line":65,"updated":"2016-02-17 15:45:25.000000000","message":"Are all of these things actually optional?","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":62,"context_line":"        password_data[\u0027user\u0027][\u0027password\u0027] \u003d password"},{"line_number":63,"context_line":"        return password_data"},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"    def _build_totp_auth(self, user_id\u003dNone, username\u003dNone,"},{"line_number":66,"context_line":"                         user_domain_id\u003dNone, user_domain_name\u003dNone,"},{"line_number":67,"context_line":"                         passcode\u003dNone):"},{"line_number":68,"context_line":"        totp_data \u003d {\u0027user\u0027: {}}"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_caef65e7","line":65,"in_reply_to":"dae33548_d04bae85","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"8497798df9886cb27520c3ed1cb3dce91cc7d451","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027id\u0027] \u003d user_domain_id"},{"line_number":76,"context_line":"                else:"},{"line_number":77,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027name\u0027] \u003d user_domain_name"},{"line_number":78,"context_line":"        totp_data[\u0027user\u0027][\u0027passcode\u0027] \u003d passcode"},{"line_number":79,"context_line":"        return totp_data"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def _build_token_auth(self, token):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_354463b5","line":78,"updated":"2016-02-18 06:07:41.000000000","message":"The only difference between password_auth and totp_auth is the passcode so suggest to refactor the common code so they can share.","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027id\u0027] \u003d user_domain_id"},{"line_number":76,"context_line":"                else:"},{"line_number":77,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027name\u0027] \u003d user_domain_name"},{"line_number":78,"context_line":"        totp_data[\u0027user\u0027][\u0027passcode\u0027] \u003d passcode"},{"line_number":79,"context_line":"        return totp_data"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def _build_token_auth(self, token):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_341e1370","line":78,"in_reply_to":"dae33548_281b66cb","updated":"2016-02-18 13:37:01.000000000","message":"Good call. I\u0027m not entirely in love with what I did, but I think it\u0027s better.","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":75,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027id\u0027] \u003d user_domain_id"},{"line_number":76,"context_line":"                else:"},{"line_number":77,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027name\u0027] \u003d user_domain_name"},{"line_number":78,"context_line":"        totp_data[\u0027user\u0027][\u0027passcode\u0027] \u003d passcode"},{"line_number":79,"context_line":"        return totp_data"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    def _build_token_auth(self, token):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_281b66cb","line":78,"in_reply_to":"dae33548_354463b5","updated":"2016-02-18 06:36:29.000000000","message":"++","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"5fe199ee202d335859ea324c60354aae7287f049","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    def _build_auth(self, user_id\u003dNone, username\u003dNone, user_domain_id\u003dNone,"},{"line_number":49,"context_line":"                    user_domain_name\u003dNone, **kwargs):"},{"line_number":50,"context_line":""},{"line_number":51,"context_line":"        # NOTE(dstanek): just to ensure sanity in the tests"},{"line_number":52,"context_line":"        self.assertEqual(1, len(kwargs),"},{"line_number":53,"context_line":"                         message\u003d\u0027_build_auth requires 1 (and only 1) \u0027"},{"line_number":54,"context_line":"                                 \u0027secret type and value\u0027)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"        secret_type, secret_value \u003d kwargs.items()[0]"},{"line_number":57,"context_line":""},{"line_number":58,"context_line":"        # NOTE(dstanek): just to ensure sanity in the tests"},{"line_number":59,"context_line":"        self.assertIn(secret_type, (\u0027passcode\u0027, \u0027password\u0027),"},{"line_number":60,"context_line":"                      message\u003d\"_build_auth only supports \u0027passcode\u0027 \""},{"line_number":61,"context_line":"                              \"and \u0027password\u0027 secret types\")"},{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        data \u003d {\u0027user\u0027: {}}"},{"line_number":64,"context_line":"        if user_id:"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_b9ccc535","line":61,"range":{"start_line":51,"start_character":8,"end_line":61,"end_character":60},"updated":"2016-02-18 17:44:41.000000000","message":"i like this","commit_id":"5a5bad7b639fb6405d9437d7eb218d7b8d5a526b"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"b1bee810185182becb6a56fff3e7bd4a06b78721","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        data[\u0027user\u0027][secret_type] \u003d secret_value"},{"line_number":75,"context_line":"        return data"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _build_totp_auth(self, user_id, username, user_domain_id,"},{"line_number":78,"context_line":"                         user_domain_name, passcode):"},{"line_number":79,"context_line":"        totp_data \u003d {\u0027user\u0027: {}}"},{"line_number":80,"context_line":"        if user_id:"},{"line_number":81,"context_line":"            totp_data[\u0027user\u0027][\u0027id\u0027] \u003d user_id"},{"line_number":82,"context_line":"        else:"},{"line_number":83,"context_line":"            totp_data[\u0027user\u0027][\u0027name\u0027] \u003d username"},{"line_number":84,"context_line":"            if user_domain_id or user_domain_name:"},{"line_number":85,"context_line":"                totp_data[\u0027user\u0027][\u0027domain\u0027] \u003d {}"},{"line_number":86,"context_line":"                if user_domain_id:"},{"line_number":87,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027id\u0027] \u003d user_domain_id"},{"line_number":88,"context_line":"                else:"},{"line_number":89,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027name\u0027] \u003d user_domain_name"},{"line_number":90,"context_line":"        totp_data[\u0027user\u0027][\u0027passcode\u0027] \u003d passcode"},{"line_number":91,"context_line":"        return totp_data"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    def _build_token_auth(self, token):"},{"line_number":94,"context_line":"        return {\u0027id\u0027: token}"}],"source_content_type":"text/x-python","patch_set":18,"id":"dae33548_efd14031","line":91,"range":{"start_line":77,"start_character":0,"end_line":91,"end_character":24},"updated":"2016-02-19 09:54:59.000000000","message":"remove this method, this method has been consolidated into `_build_auth` above, and not used anywhere.","commit_id":"71214315c035938b4bc3b557c745c1be8443a0f6"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"a46c77f25d4ee6a96dc0a8b6bc2711f62e27b617","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        data[\u0027user\u0027][secret_type] \u003d secret_value"},{"line_number":75,"context_line":"        return data"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    def _build_totp_auth(self, user_id, username, user_domain_id,"},{"line_number":78,"context_line":"                         user_domain_name, passcode):"},{"line_number":79,"context_line":"        totp_data \u003d {\u0027user\u0027: {}}"},{"line_number":80,"context_line":"        if user_id:"},{"line_number":81,"context_line":"            totp_data[\u0027user\u0027][\u0027id\u0027] \u003d user_id"},{"line_number":82,"context_line":"        else:"},{"line_number":83,"context_line":"            totp_data[\u0027user\u0027][\u0027name\u0027] \u003d username"},{"line_number":84,"context_line":"            if user_domain_id or user_domain_name:"},{"line_number":85,"context_line":"                totp_data[\u0027user\u0027][\u0027domain\u0027] \u003d {}"},{"line_number":86,"context_line":"                if user_domain_id:"},{"line_number":87,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027id\u0027] \u003d user_domain_id"},{"line_number":88,"context_line":"                else:"},{"line_number":89,"context_line":"                    totp_data[\u0027user\u0027][\u0027domain\u0027][\u0027name\u0027] \u003d user_domain_name"},{"line_number":90,"context_line":"        totp_data[\u0027user\u0027][\u0027passcode\u0027] \u003d passcode"},{"line_number":91,"context_line":"        return totp_data"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"    def _build_token_auth(self, token):"},{"line_number":94,"context_line":"        return {\u0027id\u0027: token}"}],"source_content_type":"text/x-python","patch_set":18,"id":"bae84128_bcb00c8d","line":91,"range":{"start_line":77,"start_character":0,"end_line":91,"end_character":24},"in_reply_to":"dae33548_efd14031","updated":"2016-02-19 16:14:00.000000000","message":"Done","commit_id":"71214315c035938b4bc3b557c745c1be8443a0f6"}],"keystone/tests/unit/test_v3_auth.py":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":4460,"context_line":""},{"line_number":4461,"context_line":""},{"line_number":4462,"context_line":"class TestAuthTOTP(test_v3.RestfulTestCase):"},{"line_number":4463,"context_line":"    def setUp(self):"},{"line_number":4464,"context_line":"        super(TestAuthTOTP, self).setUp()"},{"line_number":4465,"context_line":"        auth.controllers.load_auth_methods()"},{"line_number":4466,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_d300d803","line":4463,"updated":"2016-02-17 15:45:25.000000000","message":"newline","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":4460,"context_line":""},{"line_number":4461,"context_line":""},{"line_number":4462,"context_line":"class TestAuthTOTP(test_v3.RestfulTestCase):"},{"line_number":4463,"context_line":"    def setUp(self):"},{"line_number":4464,"context_line":"        super(TestAuthTOTP, self).setUp()"},{"line_number":4465,"context_line":"        auth.controllers.load_auth_methods()"},{"line_number":4466,"context_line":""}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_2a9c115c","line":4463,"in_reply_to":"dae33548_d300d803","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":4462,"context_line":"class TestAuthTOTP(test_v3.RestfulTestCase):"},{"line_number":4463,"context_line":"    def setUp(self):"},{"line_number":4464,"context_line":"        super(TestAuthTOTP, self).setUp()"},{"line_number":4465,"context_line":"        auth.controllers.load_auth_methods()"},{"line_number":4466,"context_line":""},{"line_number":4467,"context_line":"        blob, ref \u003d unit.new_totp_credential("},{"line_number":4468,"context_line":"            user_id\u003dself.default_domain_user[\u0027id\u0027],"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_dba10248","line":4465,"updated":"2016-02-18 16:12:52.000000000","message":"We should not be doing this in tests. We should override using the auth_plugin_config_override method. I have fixed in my latest patch.","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":4473,"context_line":"        r \u003d self.post(\u0027/credentials\u0027, body\u003d{\u0027credential\u0027: ref})"},{"line_number":4474,"context_line":"        self.assertValidCredentialResponse(r, ref)"},{"line_number":4475,"context_line":""},{"line_number":4476,"context_line":"    def tearDown(self):"},{"line_number":4477,"context_line":"        super(TestAuthTOTP, self).tearDown()"},{"line_number":4478,"context_line":"        cred_from_credential_api \u003d ("},{"line_number":4479,"context_line":"            self.credential_api"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_73462c50","line":4476,"updated":"2016-02-17 15:45:25.000000000","message":"Never use teardowns. They are not guaranteed to correctly teardown a test. A clearup is.","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":4473,"context_line":"        r \u003d self.post(\u0027/credentials\u0027, body\u003d{\u0027credential\u0027: ref})"},{"line_number":4474,"context_line":"        self.assertValidCredentialResponse(r, ref)"},{"line_number":4475,"context_line":""},{"line_number":4476,"context_line":"    def tearDown(self):"},{"line_number":4477,"context_line":"        super(TestAuthTOTP, self).tearDown()"},{"line_number":4478,"context_line":"        cred_from_credential_api \u003d ("},{"line_number":4479,"context_line":"            self.credential_api"}],"source_content_type":"text/x-python","patch_set":8,"id":"dae33548_eabce9bc","line":4476,"in_reply_to":"dae33548_73462c50","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"dae33548_a8b81676","updated":"2016-02-18 06:36:29.000000000","message":"still needs more tests:\n\n1) auth with no credentials\n2) auth with multiple credentials for the user\n3) auth with user name + domain name instead of unique user ID\n4) the \"corrupt credential\" exception is not tested\n5) the entire \"get_totp_token\" function is not tested","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"dae33548_054d9699","in_reply_to":"dae33548_a8b81676","updated":"2016-02-18 13:37:01.000000000","message":"Tests will be in a future patch. I\u0027m still working on them","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":4665,"context_line":"        super(TestAuthTOTP, self).auth_plugin_config_override(methods)"},{"line_number":4666,"context_line":""},{"line_number":4667,"context_line":"    def cleanup(self):"},{"line_number":4668,"context_line":"        cred \u003d self.credential_api.list_credentials_for_user("},{"line_number":4669,"context_line":"            self.default_domain_user[\u0027id\u0027], type\u003d\u0027totp\u0027)"},{"line_number":4670,"context_line":""},{"line_number":4671,"context_line":"        self.delete(\u0027/credentials/{}\u0027.format(cred[0][\u0027id\u0027]),"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_e8d97ef4","line":4668,"range":{"start_line":4668,"start_character":8,"end_line":4668,"end_character":12},"updated":"2016-02-18 06:36:29.000000000","message":"make this plural, creds*, it\u0027s a list","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":4665,"context_line":"        super(TestAuthTOTP, self).auth_plugin_config_override(methods)"},{"line_number":4666,"context_line":""},{"line_number":4667,"context_line":"    def cleanup(self):"},{"line_number":4668,"context_line":"        cred \u003d self.credential_api.list_credentials_for_user("},{"line_number":4669,"context_line":"            self.default_domain_user[\u0027id\u0027], type\u003d\u0027totp\u0027)"},{"line_number":4670,"context_line":""},{"line_number":4671,"context_line":"        self.delete(\u0027/credentials/{}\u0027.format(cred[0][\u0027id\u0027]),"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_af492a33","line":4668,"range":{"start_line":4668,"start_character":8,"end_line":4668,"end_character":12},"in_reply_to":"dae33548_e8d97ef4","updated":"2016-02-18 13:37:01.000000000","message":"Oops. Looks like I shortened the name too much.","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":4668,"context_line":"        cred \u003d self.credential_api.list_credentials_for_user("},{"line_number":4669,"context_line":"            self.default_domain_user[\u0027id\u0027], type\u003d\u0027totp\u0027)"},{"line_number":4670,"context_line":""},{"line_number":4671,"context_line":"        self.delete(\u0027/credentials/{}\u0027.format(cred[0][\u0027id\u0027]),"},{"line_number":4672,"context_line":"                    expected_status\u003dhttp_client.NO_CONTENT)"},{"line_number":4673,"context_line":""},{"line_number":4674,"context_line":"    def test_auth_with_valid_passcode(self):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_68cd6e30","line":4671,"range":{"start_line":4671,"start_character":34,"end_line":4671,"end_character":44},"updated":"2016-02-18 06:36:29.000000000","message":"nit: use %s to substitute a value as we\u0027ve been using that in most of our code","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"6c0261f95476fb8e44a2414cdf9feddd16ce230b","unresolved":false,"context_lines":[{"line_number":4668,"context_line":"        cred \u003d self.credential_api.list_credentials_for_user("},{"line_number":4669,"context_line":"            self.default_domain_user[\u0027id\u0027], type\u003d\u0027totp\u0027)"},{"line_number":4670,"context_line":""},{"line_number":4671,"context_line":"        self.delete(\u0027/credentials/{}\u0027.format(cred[0][\u0027id\u0027]),"},{"line_number":4672,"context_line":"                    expected_status\u003dhttp_client.NO_CONTENT)"},{"line_number":4673,"context_line":""},{"line_number":4674,"context_line":"    def test_auth_with_valid_passcode(self):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_a8ead671","line":4671,"range":{"start_line":4671,"start_character":8,"end_line":4671,"end_character":60},"updated":"2016-02-18 06:36:29.000000000","message":"why not loop through and delete all credentials instead of risking the index error with [0]","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"5324b35f8cdbe1ae5b96843981466b08f1e98612","unresolved":false,"context_lines":[{"line_number":4668,"context_line":"        cred \u003d self.credential_api.list_credentials_for_user("},{"line_number":4669,"context_line":"            self.default_domain_user[\u0027id\u0027], type\u003d\u0027totp\u0027)"},{"line_number":4670,"context_line":""},{"line_number":4671,"context_line":"        self.delete(\u0027/credentials/{}\u0027.format(cred[0][\u0027id\u0027]),"},{"line_number":4672,"context_line":"                    expected_status\u003dhttp_client.NO_CONTENT)"},{"line_number":4673,"context_line":""},{"line_number":4674,"context_line":"    def test_auth_with_valid_passcode(self):"}],"source_content_type":"text/x-python","patch_set":12,"id":"dae33548_0f03f6b8","line":4671,"range":{"start_line":4671,"start_character":8,"end_line":4671,"end_character":60},"in_reply_to":"dae33548_a8ead671","updated":"2016-02-18 13:37:01.000000000","message":"good call","commit_id":"7fe389e0ec40a78299e53b698a76a8c83a5a0d52"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"5fe199ee202d335859ea324c60354aae7287f049","unresolved":false,"context_lines":[{"line_number":29,"context_line":"from testtools import testcase"},{"line_number":30,"context_line":""},{"line_number":31,"context_line":"from keystone import auth"},{"line_number":32,"context_line":"from keystone.common.totp import get_totp_token"},{"line_number":33,"context_line":"from keystone.common import utils"},{"line_number":34,"context_line":"from keystone.contrib.revoke import routers"},{"line_number":35,"context_line":"from keystone import exception"}],"source_content_type":"text/x-python","patch_set":13,"id":"dae33548_19e7b1ac","line":32,"range":{"start_line":32,"start_character":0,"end_line":32,"end_character":47},"updated":"2016-02-18 17:44:41.000000000","message":"womp womp","commit_id":"5a5bad7b639fb6405d9437d7eb218d7b8d5a526b"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"4c2d331627751b6662f5ce307c3c6ff877743551","unresolved":false,"context_lines":[{"line_number":4694,"context_line":"            project_id\u003dself.project[\u0027id\u0027])"},{"line_number":4695,"context_line":""},{"line_number":4696,"context_line":"    def cleanup(self):"},{"line_number":4697,"context_line":"        creds \u003d self.credential_api.list_credentials_for_user("},{"line_number":4698,"context_line":"            self.default_domain_user[\u0027id\u0027], type\u003d\u0027totp\u0027)"},{"line_number":4699,"context_line":""},{"line_number":4700,"context_line":"        for cred in creds:"},{"line_number":4701,"context_line":"            self.delete(\u0027/credentials/%s\u0027 % cred[\u0027id\u0027],"},{"line_number":4702,"context_line":"                        expected_status\u003dhttp_client.NO_CONTENT)"},{"line_number":4703,"context_line":""},{"line_number":4704,"context_line":"        creds \u003d self.credential_api.list_credentials_for_user("},{"line_number":4705,"context_line":"            self.default_domain_user[\u0027id\u0027], type\u003d\u0027other\u0027)"},{"line_number":4706,"context_line":""},{"line_number":4707,"context_line":"        for cred in creds:"},{"line_number":4708,"context_line":"            self.delete(\u0027/credentials/%s\u0027 % cred[\u0027id\u0027],"}],"source_content_type":"text/x-python","patch_set":15,"id":"dae33548_23e6a9e8","line":4705,"range":{"start_line":4697,"start_character":8,"end_line":4705,"end_character":57},"updated":"2016-02-19 05:51:05.000000000","message":"let\u0027s combine these lists and do one delete","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"4c2d331627751b6662f5ce307c3c6ff877743551","unresolved":false,"context_lines":[{"line_number":4716,"context_line":"        self.v3_create_token(auth_data, expected_status\u003dhttp_client.CREATED)"},{"line_number":4717,"context_line":""},{"line_number":4718,"context_line":"    def test_with_an_invalid_passcode_and_user_credentials(self):"},{"line_number":4719,"context_line":"        self._make_credentials(\u0027totp\u0027, count\u003d1)"},{"line_number":4720,"context_line":"        auth_data \u003d self._make_auth_data_by_id(\u0027000000\u0027)"},{"line_number":4721,"context_line":"        self.v3_create_token(auth_data,"},{"line_number":4722,"context_line":"                             expected_status\u003dhttp_client.UNAUTHORIZED)"}],"source_content_type":"text/x-python","patch_set":15,"id":"dae33548_23fd096f","line":4719,"range":{"start_line":4719,"start_character":39,"end_line":4719,"end_character":46},"updated":"2016-02-19 05:51:05.000000000","message":"this is the default","commit_id":"5343b2b9f40ff46d56b2a680f63e8abee6baf536"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"b1bee810185182becb6a56fff3e7bd4a06b78721","unresolved":false,"context_lines":[{"line_number":4724,"context_line":"        self.v3_create_token(auth_data,"},{"line_number":4725,"context_line":"                             expected_status\u003dhttp_client.UNAUTHORIZED)"},{"line_number":4726,"context_line":""},{"line_number":4727,"context_line":"    def test_with_a_corrupt_passcode(self):"},{"line_number":4728,"context_line":"        self._make_credentials(\u0027totp\u0027)"},{"line_number":4729,"context_line":"        auth_data \u003d self._make_auth_data_by_id(\u0027000\u0027)"},{"line_number":4730,"context_line":"        self.v3_create_token(auth_data,"},{"line_number":4731,"context_line":"                             expected_status\u003dhttp_client.UNAUTHORIZED)"},{"line_number":4732,"context_line":""},{"line_number":4733,"context_line":"    def test_with_multiple_credentials(self):"},{"line_number":4734,"context_line":"        self._make_credentials(\u0027other\u0027, 3)"}],"source_content_type":"text/x-python","patch_set":18,"id":"bae84128_296fb593","line":4731,"range":{"start_line":4727,"start_character":0,"end_line":4731,"end_character":70},"updated":"2016-02-19 09:54:59.000000000","message":"seen from how it is authenticated, this is basically the same thing as `test_with_an_invalid_passcode_and_user_credentials`, \n\nIf we want to test the passcode is corrupted, generate the passcode and hack it instead.","commit_id":"71214315c035938b4bc3b557c745c1be8443a0f6"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"a46c77f25d4ee6a96dc0a8b6bc2711f62e27b617","unresolved":false,"context_lines":[{"line_number":4724,"context_line":"        self.v3_create_token(auth_data,"},{"line_number":4725,"context_line":"                             expected_status\u003dhttp_client.UNAUTHORIZED)"},{"line_number":4726,"context_line":""},{"line_number":4727,"context_line":"    def test_with_a_corrupt_passcode(self):"},{"line_number":4728,"context_line":"        self._make_credentials(\u0027totp\u0027)"},{"line_number":4729,"context_line":"        auth_data \u003d self._make_auth_data_by_id(\u0027000\u0027)"},{"line_number":4730,"context_line":"        self.v3_create_token(auth_data,"},{"line_number":4731,"context_line":"                             expected_status\u003dhttp_client.UNAUTHORIZED)"},{"line_number":4732,"context_line":""},{"line_number":4733,"context_line":"    def test_with_multiple_credentials(self):"},{"line_number":4734,"context_line":"        self._make_credentials(\u0027other\u0027, 3)"}],"source_content_type":"text/x-python","patch_set":18,"id":"bae84128_effc9840","line":4731,"range":{"start_line":4727,"start_character":0,"end_line":4731,"end_character":70},"in_reply_to":"bae84128_296fb593","updated":"2016-02-19 16:14:00.000000000","message":"Done","commit_id":"71214315c035938b4bc3b557c745c1be8443a0f6"},{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"b1bee810185182becb6a56fff3e7bd4a06b78721","unresolved":false,"context_lines":[{"line_number":4739,"context_line":"        self.v3_create_token(auth_data, expected_status\u003dhttp_client.CREATED)"},{"line_number":4740,"context_line":""},{"line_number":4741,"context_line":"    def test_with_multiple_users(self):"},{"line_number":4742,"context_line":"        # make some credentials for a user"},{"line_number":4743,"context_line":"        self._make_credentials(\u0027totp\u0027, count\u003d3)"},{"line_number":4744,"context_line":""},{"line_number":4745,"context_line":"        # create a new user and their credentials"}],"source_content_type":"text/x-python","patch_set":18,"id":"bae84128_899361fa","line":4742,"range":{"start_line":4742,"start_character":36,"end_line":4742,"end_character":42},"updated":"2016-02-19 09:54:59.000000000","message":"the existing user","commit_id":"71214315c035938b4bc3b557c745c1be8443a0f6"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"a46c77f25d4ee6a96dc0a8b6bc2711f62e27b617","unresolved":false,"context_lines":[{"line_number":4739,"context_line":"        self.v3_create_token(auth_data, expected_status\u003dhttp_client.CREATED)"},{"line_number":4740,"context_line":""},{"line_number":4741,"context_line":"    def test_with_multiple_users(self):"},{"line_number":4742,"context_line":"        # make some credentials for a user"},{"line_number":4743,"context_line":"        self._make_credentials(\u0027totp\u0027, count\u003d3)"},{"line_number":4744,"context_line":""},{"line_number":4745,"context_line":"        # create a new user and their credentials"}],"source_content_type":"text/x-python","patch_set":18,"id":"bae84128_fc58d458","line":4742,"range":{"start_line":4742,"start_character":36,"end_line":4742,"end_character":42},"in_reply_to":"bae84128_899361fa","updated":"2016-02-19 16:14:00.000000000","message":"Done","commit_id":"71214315c035938b4bc3b557c745c1be8443a0f6"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"e7d966b9fb8b77991791027be4d5268e2ecb7d56","unresolved":false,"context_lines":[{"line_number":4745,"context_line":"        self._make_credentials(\u0027totp\u0027, count\u003d1, blob\u003d\u00270\u0027)"},{"line_number":4746,"context_line":"        auth_data \u003d self._make_auth_data_by_id(\u0027000000\u0027)"},{"line_number":4747,"context_line":"        self.v3_create_token(auth_data,"},{"line_number":4748,"context_line":"                             expected_status\u003dhttp_client.UNAUTHORIZED)"},{"line_number":4749,"context_line":""},{"line_number":4750,"context_line":"    def test_with_multiple_credentials(self):"},{"line_number":4751,"context_line":"        self._make_credentials(\u0027other\u0027, 3)"}],"source_content_type":"text/x-python","patch_set":19,"id":"bae84128_a2b0dede","line":4748,"range":{"start_line":4748,"start_character":57,"end_line":4748,"end_character":69},"updated":"2016-02-19 18:21:02.000000000","message":"this is now a 400","commit_id":"0a2e5317a221120a23502ef77cbbb1176e23c5fd"}],"keystone/totp/__init__.py":[{"author":{"_account_id":7191,"name":"Jamie Lennox","email":"jamielennox@gmail.com","username":"jamielennox"},"change_message_id":"edb538459d35e3e5f765923f328db0d0978ba0f8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"5a5ae5dd_0db543cf","line":1,"updated":"2016-02-09 07:36:54.000000000","message":"this shouldn\u0027t be in keystone/totp. the root directory like this has typically been for backends. This should at least be in utils or common.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"3a57f1b5_7abd21b6","line":1,"in_reply_to":"5a5ae5dd_0db543cf","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"}],"keystone/totp/core.py":[{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"c3d99fafc624bb8d92b191ed23d89f25c60d93a9","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2013 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a5de9d1_e2581f8c","line":1,"range":{"start_line":1,"start_character":0,"end_line":1,"end_character":37},"updated":"2016-02-01 22:12:12.000000000","message":"switch up copyright","commit_id":"1139da65d9ddcb94a1aa56aeca7d7f3c875f5c17"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"3d5fa7d55aa9107c579498ed6590a9212aaef1a4","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2013 OpenStack Foundation"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"# not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a5de9d1_5e5bd92e","line":1,"range":{"start_line":1,"start_character":0,"end_line":1,"end_character":37},"in_reply_to":"7a5de9d1_e2581f8c","updated":"2016-02-02 19:41:18.000000000","message":"Done","commit_id":"1139da65d9ddcb94a1aa56aeca7d7f3c875f5c17"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"c3d99fafc624bb8d92b191ed23d89f25c60d93a9","unresolved":false,"context_lines":[{"line_number":18,"context_line":"import struct"},{"line_number":19,"context_line":"import time"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"def get_hotp_token(secret, intervals_no):"},{"line_number":23,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":24,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a5de9d1_a27a27bb","line":21,"updated":"2016-02-01 22:12:12.000000000","message":"definitely needs a module level docstring explaining what\u0027s going on and how this all works","commit_id":"1139da65d9ddcb94a1aa56aeca7d7f3c875f5c17"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"3d5fa7d55aa9107c579498ed6590a9212aaef1a4","unresolved":false,"context_lines":[{"line_number":18,"context_line":"import struct"},{"line_number":19,"context_line":"import time"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"def get_hotp_token(secret, intervals_no):"},{"line_number":23,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":24,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a5de9d1_f995ff87","line":21,"in_reply_to":"7a5de9d1_a27a27bb","updated":"2016-02-02 19:41:18.000000000","message":"Done","commit_id":"1139da65d9ddcb94a1aa56aeca7d7f3c875f5c17"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3d2a28c5880351361821298d5fbe97bdd554b750","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a5de9d1_a7f8b94a","line":35,"updated":"2016-02-02 22:07:08.000000000","message":"nit: we should add an additional doc string for what this method returns.","commit_id":"2b7cbd2926f610c87df00daae805f67d153e0604"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3d2a28c5880351361821298d5fbe97bdd554b750","unresolved":false,"context_lines":[{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o+4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"7a5de9d1_c73e1529","line":41,"updated":"2016-02-02 22:07:08.000000000","message":"this is missing whitespace around the operator.\n\nhttp://logs.openstack.org/01/274901/2/check/gate-keystone-linters/ee75f02/console.html","commit_id":"2b7cbd2926f610c87df00daae805f67d153e0604"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3d2a28c5880351361821298d5fbe97bdd554b750","unresolved":false,"context_lines":[{"line_number":45,"context_line":"def get_totp_token(secret):"},{"line_number":46,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":"    return get_hotp_token(secret, intervals_no\u003dint(time.time())//30)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a5de9d1_67f2c171","line":48,"updated":"2016-02-02 22:07:08.000000000","message":"nit: we should add an additional doc string for what this method returns.","commit_id":"2b7cbd2926f610c87df00daae805f67d153e0604"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"3d2a28c5880351361821298d5fbe97bdd554b750","unresolved":false,"context_lines":[{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":"    return get_hotp_token(secret, intervals_no\u003dint(time.time())//30)"}],"source_content_type":"text/x-python","patch_set":2,"id":"7a5de9d1_c78855c9","line":50,"updated":"2016-02-02 22:07:08.000000000","message":"nit: this is missing whitespace around the arithmetic operator (/).","commit_id":"2b7cbd2926f610c87df00daae805f67d153e0604"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"a113b81a5fd6088112a1cfc15b6434ddd80d6935","unresolved":false,"context_lines":[{"line_number":20,"context_line":"\"\"\"Time-based One-time Password Algorithm (TOTP) is an algorithm that computes"},{"line_number":21,"context_line":"a one-time password from a shared secret key and the current time."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"TOTP is an example of a hash-based message authentication code (HMAC). It"},{"line_number":24,"context_line":"combines a secret key with the current timestamp using a cryptographic hash"},{"line_number":25,"context_line":"function to generate a one-time password. The timestamp typically increases in"},{"line_number":26,"context_line":"30-second intervals, so passwords generated close together in time from the"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_88190e25","line":23,"updated":"2016-02-09 14:24:20.000000000","message":"is TOTP an example of HMAC or an implementation?","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":20,"context_line":"\"\"\"Time-based One-time Password Algorithm (TOTP) is an algorithm that computes"},{"line_number":21,"context_line":"a one-time password from a shared secret key and the current time."},{"line_number":22,"context_line":""},{"line_number":23,"context_line":"TOTP is an example of a hash-based message authentication code (HMAC). It"},{"line_number":24,"context_line":"combines a secret key with the current timestamp using a cryptographic hash"},{"line_number":25,"context_line":"function to generate a one-time password. The timestamp typically increases in"},{"line_number":26,"context_line":"30-second intervals, so passwords generated close together in time from the"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_71c9bf25","line":23,"in_reply_to":"5a5ae5dd_88190e25","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"0ac298739e5cc6ac1be0a99627a12a08a764df09","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_e2231fa6","line":35,"range":{"start_line":35,"start_character":24,"end_line":35,"end_character":26},"updated":"2016-02-09 02:30:40.000000000","message":"nit: 2 spaces","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_f1560f5b","line":35,"in_reply_to":"5a5ae5dd_a8edeaf0","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_515da377","line":35,"range":{"start_line":35,"start_character":24,"end_line":35,"end_character":26},"in_reply_to":"5a5ae5dd_e2231fa6","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"a113b81a5fd6088112a1cfc15b6434ddd80d6935","unresolved":false,"context_lines":[{"line_number":32,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_a8edeaf0","line":35,"in_reply_to":"5a5ae5dd_e2231fa6","updated":"2016-02-09 14:24:20.000000000","message":"We should also add a return docstring","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"0ac298739e5cc6ac1be0a99627a12a08a764df09","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o + 4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def get_totp_token(secret):"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_82aeebe5","line":42,"range":{"start_line":37,"start_character":4,"end_line":42,"end_character":35},"updated":"2016-02-09 02:30:40.000000000","message":"so, same comment as previous patch set; we\u0027ll be maintaining this code, and this is doing very specific non-obvious operations. I would have no idea how to begin to debug this if a new bug came up.\n\ncan you add comments that explain what the code is doing? or a link to sample implementation/docs?","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o + 4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def get_totp_token(secret):"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_11dbabed","line":42,"range":{"start_line":37,"start_character":4,"end_line":42,"end_character":35},"in_reply_to":"3a57f1b5_ab9e6a05","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":1916,"name":"Guang Yee","email":"gyee@suse.com","username":"guang-yee"},"change_message_id":"4dd6a64d722d4db6b090930fb19ccd091e60cdbb","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o + 4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def get_totp_token(secret):"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_ab9e6a05","line":42,"range":{"start_line":37,"start_character":4,"end_line":42,"end_character":35},"in_reply_to":"5a5ae5dd_2d935f51","updated":"2016-02-09 20:01:39.000000000","message":"Can\u0027t we leverage this?\n\nhttps://cryptography.io/en/latest/hazmat/primitives/twofactor/","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o + 4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def get_totp_token(secret):"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_f1ddafe0","line":42,"range":{"start_line":37,"start_character":4,"end_line":42,"end_character":35},"in_reply_to":"5a5ae5dd_2d935f51","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o + 4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def get_totp_token(secret):"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_319d870a","line":42,"range":{"start_line":37,"start_character":4,"end_line":42,"end_character":35},"in_reply_to":"5a5ae5dd_82aeebe5","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":2903,"name":"Morgan Fainberg","email":"morgan.fainberg@gmail.com","username":"mdrnstm"},"change_message_id":"c6680bb173ec770a79a873d85c77bf00481d5cff","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o + 4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def get_totp_token(secret):"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_9d508e60","line":42,"range":{"start_line":37,"start_character":4,"end_line":42,"end_character":35},"in_reply_to":"5a5ae5dd_82aeebe5","updated":"2016-02-09 03:07:21.000000000","message":"is unicode correct or is six.text_type correct?","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o + 4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def get_totp_token(secret):"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_51d4c3bb","line":42,"range":{"start_line":37,"start_character":4,"end_line":42,"end_character":35},"in_reply_to":"5a5ae5dd_9d508e60","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":7191,"name":"Jamie Lennox","email":"jamielennox@gmail.com","username":"jamielennox"},"change_message_id":"edb538459d35e3e5f765923f328db0d0978ba0f8","unresolved":false,"context_lines":[{"line_number":34,"context_line":"    :param secret: A secret for the HOTP authentication"},{"line_number":35,"context_line":"    :param intervals_no:  counter for the algorithm"},{"line_number":36,"context_line":"    \"\"\""},{"line_number":37,"context_line":"    key \u003d base64.b32decode(secret, True)"},{"line_number":38,"context_line":"    msg \u003d struct.pack(\"\u003eQ\", intervals_no)"},{"line_number":39,"context_line":"    h \u003d hmac.new(key, msg, hashlib.sha1).digest()"},{"line_number":40,"context_line":"    o \u003d ord(h[19]) \u0026 15"},{"line_number":41,"context_line":"    h \u003d (struct.unpack(\"\u003eI\", h[o:o + 4])[0] \u0026 0x7fffffff) % 1000000"},{"line_number":42,"context_line":"    return unicode(h).rjust(6, \u00270\u0027)"},{"line_number":43,"context_line":""},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"def get_totp_token(secret):"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_2d935f51","line":42,"range":{"start_line":37,"start_character":4,"end_line":42,"end_character":35},"in_reply_to":"5a5ae5dd_9d508e60","updated":"2016-02-09 07:36:54.000000000","message":"I know it\u0027s not much code but i don\u0027t want to maintain this. \n\nThere are a number of libraries that support totp in python including (apparently) cryptography and we should consume it.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":5046,"name":"Lance Bragstad","email":"lbragstad@redhat.com","username":"ldbragst"},"change_message_id":"a113b81a5fd6088112a1cfc15b6434ddd80d6935","unresolved":false,"context_lines":[{"line_number":45,"context_line":"def get_totp_token(secret):"},{"line_number":46,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":"    return get_hotp_token(secret, intervals_no\u003dint(time.time()) // 30)"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_68be12d6","line":48,"updated":"2016-02-09 14:24:20.000000000","message":"We should add a return doc string.","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":45,"context_line":"def get_totp_token(secret):"},{"line_number":46,"context_line":"    \"\"\"Generate HOTP code."},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":"    return get_hotp_token(secret, intervals_no\u003dint(time.time()) // 30)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_b1e3b7a3","line":48,"in_reply_to":"5a5ae5dd_68be12d6","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":6482,"name":"Steve Martinelli","email":"s.martinelli@gmail.com","username":"stevemar"},"change_message_id":"0ac298739e5cc6ac1be0a99627a12a08a764df09","unresolved":false,"context_lines":[{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":"    return get_hotp_token(secret, intervals_no\u003dint(time.time()) // 30)"}],"source_content_type":"text/x-python","patch_set":3,"id":"5a5ae5dd_62b5ef2f","line":50,"range":{"start_line":50,"start_character":11,"end_line":50,"end_character":70},"updated":"2016-02-09 02:30:40.000000000","message":"same as above","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"},{"author":{"_account_id":11434,"name":"werner mendizabal","email":"nonameentername@gmail.com","username":"nonameentername"},"change_message_id":"24599b9d765c2d3f1109d7adaee40c703f2dfd57","unresolved":false,"context_lines":[{"line_number":47,"context_line":""},{"line_number":48,"context_line":"    :param secret: A secret for the TOTP authentication"},{"line_number":49,"context_line":"    \"\"\""},{"line_number":50,"context_line":"    return get_hotp_token(secret, intervals_no\u003dint(time.time()) // 30)"}],"source_content_type":"text/x-python","patch_set":3,"id":"3a57f1b5_71f0df67","line":50,"range":{"start_line":50,"start_character":11,"end_line":50,"end_character":70},"in_reply_to":"5a5ae5dd_62b5ef2f","updated":"2016-02-11 20:05:49.000000000","message":"Done","commit_id":"f365fb43de24b75c31cd8200335b7f7167fdcba3"}],"releasenotes/notes/totp-40d93231714c6a20.yaml":[{"author":{"_account_id":13063,"name":"WEI CHEN","email":"dave.jungler@gmail.com","username":"wei.d.chen"},"change_message_id":"b1bee810185182becb6a56fff3e7bd4a06b78721","unresolved":false,"context_lines":[{"line_number":5,"context_line":"   Keystone now supports authenticating via Time-based One-time Password (TOTP)."},{"line_number":6,"context_line":"   To enable this feature, add the ``totp`` auth plugin to the ``methods``"},{"line_number":7,"context_line":"   option in the ``[auth]`` section of ``keystone.conf``. More information"},{"line_number":8,"context_line":"   about using TOTP can be found in keystone\u0027s documentation."}],"source_content_type":"text/x-yaml","patch_set":18,"id":"bae84128_800336b8","line":8,"range":{"start_line":8,"start_character":36,"end_line":8,"end_character":60},"updated":"2016-02-19 09:54:59.000000000","message":"link to \"auth-totp.rst\"?","commit_id":"71214315c035938b4bc3b557c745c1be8443a0f6"}],"setup.cfg":[{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"a2071b88d78b7d673de89b54c3cef751591a21c8","unresolved":false,"context_lines":[{"line_number":89,"context_line":"keystone.auth.oauth1 \u003d"},{"line_number":90,"context_line":"    default \u003d keystone.auth.plugins.oauth1:OAuth"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"keystone.auth.totp \u003d"},{"line_number":93,"context_line":"    default \u003d keystone.auth.plugins.totp:TOTP"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"keystone.auth.openid \u003d"}],"source_content_type":"text/x-ttcn-cfg","patch_set":8,"id":"dae33548_738bcc68","line":92,"updated":"2016-02-17 15:45:25.000000000","message":"probably best to keep ordered","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"},{"author":{"_account_id":7725,"name":"David Stanek","email":"dstanek@dstanek.com","username":"dstanek"},"change_message_id":"36c6ac471c9ff2b480d38be4aa4013a29ee7a2e9","unresolved":false,"context_lines":[{"line_number":89,"context_line":"keystone.auth.oauth1 \u003d"},{"line_number":90,"context_line":"    default \u003d keystone.auth.plugins.oauth1:OAuth"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"keystone.auth.totp \u003d"},{"line_number":93,"context_line":"    default \u003d keystone.auth.plugins.totp:TOTP"},{"line_number":94,"context_line":""},{"line_number":95,"context_line":"keystone.auth.openid \u003d"}],"source_content_type":"text/x-ttcn-cfg","patch_set":8,"id":"dae33548_4ae515da","line":92,"in_reply_to":"dae33548_738bcc68","updated":"2016-02-18 16:12:52.000000000","message":"Done","commit_id":"5257c53a6a16896ddb1064d3be6c42f4475f64a6"}]}
