Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99

Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1169

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 1176
8000 Add scope and hashing to api keys by sonalkr132 · Pull Request #1962 · rubygems/rubygems.org · GitHub
Nothing Special   »   [go: up one dir, main page]

Skip to content

Conversation

sonalkr132
Copy link
Member
@sonalkr132 sonalkr132 commented Apr 21, 2019

This allows the user to create multiple API keys and set scope/permission per API key. The key will be shown to the user only once after creation.

todo

  • add tests
  • script to migrate user.api_key to api_keys table

@eliotsykes
Copy link
Contributor
eliotsykes commented Apr 22, 2019

It looks like the existing users.api_key column is going to be kept around. Consider renaming it so its name isn't easily confused with the new API keys and better explains its new purpose. Ignore, I've re-read the PR and seen the task about migrating this - apologies.

@sonalkr132 sonalkr132 mentioned this pull request Apr 24, 2019
@sonalkr132 sonalkr132 force-pushed the api-keys branch 2 times, most recently from 054da28 to 15435e7 Compare May 9, 2019 21:03
@sonalkr132
Copy link
Member Author
sonalkr132 commented May 11, 2019

Updated to add tests and rake task for migration to ApiKey model.

This removes /api/v1/api_key which would mean gem signin would stop working. I doubt we need a smoother migration strategy than flip switch (with a sunset period), the aforementioned endpoint gets low traffic and supporting both plain text and hashed keys would be complicated.

About expiry of keys in 6 months and automation of renewal, we could add an exclusive scope for create api_key which would act like refresh_token and have no expiry. However, adding refresh token doesn't seem as clear cut to me, it feels like re-inventing the wheel. I am not sure we should migrate to OAuth or support it as an alternative, instead of adding refresh token to our implementation. Request signing also seems a reasonable alternative.

Email notification can be taken up in separate PR and preferably after we have deployed email fail safe.

EDIT: strike outdated comment.

@sonalkr132 sonalkr132 force-pushed the api-keys branch 2 times, most recently from 9f30c93 to d7cea0b Compare July 14, 2019 21:13
@sonalkr132 sonalkr132 changed the title Add expiry, scope and hashing to api keys Add scope to api keys Jul 14, 2019
@sonalkr132 sonalkr132 changed the title Add scope to api keys Add scope and hashing to api keys Jul 22, 2019
@sonalkr132
Copy link
Member Author

I removed the expiry part after discussion in #rubygems-org. Manual update it too much of an ask and most implementations don't do this (Github access token, AWS etc).

Changes in this PR:

  • API authentication will be done from user.api_keys' scope instead of user.api_key
  • New API keys will be prefixed with rubygems_ and stored as hashs.
  • Existing user.api_key will be copied (after hashing) to user.api_keys (full scope). Reset of user.api_key is removed. Deletion of user.api_keys will be used for revocation.
  • GET api/v1/api_key will continue to serve user.api_key as older clients use it in gem signin. Newer clients will use POST api/v1/api_key in gem signin and it will create a new key on each invocation.
  • Send mail to user when new API is created

Please let me know if it has further room for improvement.

private

def check_mfa(user)
if user&.mfa_api_authorized?(otp)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider tweaking so BaseController#verify_with_otp can be used here too, allowing this security-related code to be defined in a single place so vulnerabilities are less likely to slip through reviews.

Copy link
Member Author
@sonalkr132 sonalkr132 Aug 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had raised the same issue it was first introduced.

verify_with_otp requires @api_user set.

We could pass user as an optional argument to verify_with_otp, however, it would end up returning an incorrect response when authentication fails return if user&.mfa_api_authorized?(otp) (user being nil).
I am sure there is a way we can handle all case correctly, but it would be too complicated/risky to fix here. We can take this up in a separate PR.

api_key = request.headers["Authorization"] || params.permit(:api_key).fetch(:api_key, "")
@api_user = User.find_by_api_key(api_key)
def find_api_key
params_key = request.headers["Authorization"] || params.permit(:api_key).fetch(:api_key, "")

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

@sonalkr132 sonalkr132 force-pushed the api-keys branch 2 times, most recently from 25ff404 to d8710d7 Compare August 3, 2019 11:32
@sonalkr132
Copy link
Member Author

Thank you for review @eliotsykes ❤️
All of them were valid concerns. I have resolved most of them and left comments on others.

Copy link
Contributor
@eliotsykes eliotsykes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @sonalkr132, just one minor bit of feedback about the rake task. Thanks for being cool about the review, this is looking even better.

@indirect
Copy link
Contributor

This is a great improvement, thank you! 🙌

IMO, we should provide a ~1-2 year deprecation period where the current RubyGems gem signin keeps working, before forcing everyone to update to the latest RubyGems. I would suggest:

  • migrate existing API key, storing only a hash, and removing dashboard scope (so currently logged in users stay logged in)
  • current RubyGems client can run gem signin and get a new API key with all scopes except dashboard
  • future RubyGems client can run gem signin and get a new API with only requested scopes
  • the reset endpoint should delete all existing API keys for the account

What do you think?

@indirect
Copy link
Contributor

@sonalkr132 awesome, thank you! Is there an easy way we can test running gem signing against this PR? Maybe deploy this branch to staging for a bit?

@sonalkr132
Copy link
Member Author

migrate existing API key, storing only a hash, and removing dashboard scope (so currently logged in users stay logged in)
current RubyGems client can run gem signin and get a new API key with all scopes except dashboard

These two are already part of the changes.

Maybe deploy this branch to staging for a bit?

This is deployed on staging now. I tested with the following commands:

$ gem signin --host https://staging.rubygems.org
$ gem push ~/hola/thinggg1-4.1.41.gem --host https://staging.rubygems.org
$ gem signout && gem push ~/hola/thinggg1-4.1.42.gem --host https://staging.rubygems.org

Copy link
Member
@colby-swandale colby-swandale left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have more feedback, but i don't want to flood you with a ton of feedback all at once. I think that this is a good first step but some minor details needs to be worked out.

if @api_key.save
Mailer.delay.api_key_created(@api_key.id)

flash[:notice] = t(".save_key", key: key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this PR on my dev machine and didn't notice that the API key was in the notification bar (which IMO is not great already) until i clicked to go to another page.

Can we instead make a panel above the API keys that shows this message instead, and with the API key specifically highlighted/bold

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot from 2020-07-25 01-29-06
I hope this works.

belongs_to :user
validates :user, :name, :hashed_key, presence: true
validate :exclusive_show_dashboard_scope, if: :show_dashboard?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple API keys are able to have the same nickname, I think we should have a unique validation on name to avoid confusion for users and avoid accidentally deleting the wrong API key. Thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inforcing name uniqueness will mean the user will have to face some frustration when signing in from cli (where they can't see the existing names) and keep getting asked to enter email and password. Also, we would have to add random bits to the default key name we are suggesting in cli.

If you think these issues don't compare to what you are pointing out, we can add name uniqueness. I don't have any strong opinion about this, I was just leaning towards not making users fail their signin attempts.

@sonalkr132
Copy link
Member Author

@colby-swandale I have incorporated all of your UI suggestions. Please let me know if there is anything else.

@sonalkr132 sonalkr132 force-pushed the api-keys branch 4 times, most recently from 6a39b02 to 326df46 Compare September 20, 2020 08:45
@sonalkr132 sonalkr132 force-pushed the api-keys branch 2 times, most recently from 12d51df to e2df5ec Compare September 26, 2020 14:27
@sonalkr132 sonalkr132 mentioned this pull request Sep 29, 2020
5 tasks
@sonalkr132 sonalkr132 force-pushed the api-keys branch 2 times, most recently from e84961f to 87804e0 Compare October 6, 2020 08:55
@sonalkr132 sonalkr132 force-pushed the api-keys branch 3 times, most recently from b6d599a to 620ca75 Compare December 16, 2020 05:11
permissions

Our api key implementation had room for improvements, namely:
    - set expiry time
    - stored hashed token in DB instead of plain text
    - support multiple api keys
    - limit permission per api key

api token will be shown to user only once and will expire after 180
days. users can pick which permissions do they want to enable per
token.

Add controller and view for api keys

Verify api key authorization for api requests

Update existing test to use api keys model

deprecates api endpoint to get api keys. users can see api key
only once during creation.
removes related tests for get api keys and unyank endpoints.

Add i18n keys

Add tests for api keys

Add test for missing api key scope

Add rake task to migrate api keys

Update before action to use redirect_to_signin

Remove expires_at column

Remove unused i18n keys and api reset option

fix tests and add prefix to api keys

Rever changes to throttling test for api keys

Add create action to api keys endpoint

This will be used by new rubygems client when user runs:
`gem signin`. Older clients will continue to get `user.api_key`.

Add mail to api key creation

Update rack attack tests to use api_keys

Fix casing of API in i18n

Improve naming of methods used in api keys

Make show dashboard an exclusive scope

Increase API key byte length

Use seperate api_key_params method for api and ui endpoints. Rails
was getting confused about nested params being string when encoded
with `URI.encode_www_form` (in the client).

legacy API keys were not necessarily insecure with 16 bytes of
randomness. Colby recommended that it was a good time to increase the
byte length along with other changes.

Don't add show_dashboard scope to legacy-key

Add action to reset all API keys

Update GET api_key endpoint to create new key on each request

this would ensure that clients which can't migrate to using POST
endpoint continue to work as is and allow us not to store any
unercypted keys.

Use partial for compromised instructions

UI improvements

Changes mostly as per colby's suggestions on the PR.

Add method to udpate api_key and add validation on name

In cli we want to start with minimum possible permission and update
scope as they execute additional commands.

Add functional test for api_key update

Fix news tests added after rebase

Migrate css to existing owners table

Update method names to can prefix and add last access
@sonalkr132 sonalkr132 merged commit 55d7e0d into rubygems:master Dec 16, 2020
@sonalkr132 sonalkr132 deleted the api-keys branch December 16, 2020 06:26
@sonalkr132 sonalkr132 temporarily deployed to staging December 16, 2020 07:03 Inactive
@sonalkr132 sonalkr132 temporarily deployed to production December 16, 2020 11:59 Inactive
@sonalkr132 sonalkr132 mentioned this pull request Jul 16, 2021
Closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

0