Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Client Credentials grant #129

Merged
merged 2 commits into from
Sep 28, 2018
Merged

Conversation

joshcanhelp
Copy link
Contributor

@joshcanhelp joshcanhelp commented Sep 14, 2018

This PR adds a method to get an API access token with a Client Credentials grant is no token is passed directly to Auth0::Client during instantiation.

Specific changes:

  • Add Auth0::Api::AuthenticationEndpoints::api_token method that accepts an audience (defaults to the Management API audience for the domain used), performs a Client Credentials grant, and returns a hash of what was returned.
  • Add a check during Auth0::Client instantiation to call this added method if no token was passed
  • Add unit tests for new functionality and existing functionality

Usage:

To start using this new functionality, leave out token and access_token and add client_secret when instantiating Auth0::Client:

# Set the Auth0 API client
def auth0_client
  # This assumes you're using env variables.
  @auth0_client ||= Auth0::Client.new(
    # REMOVE: token: ENV['AUTH0_RUBY_API_TOKEN'],
    # REMOVE: access_token: ENV['AUTH0_RUBY_API_TOKEN'],
    client_id:  ENV['AUTH0_RUBY_CLIENT_ID'],
    client_secret: ENV['AUTH0_RUBY_CLIENT_SECRET'],
    domain: ENV['AUTH0_RUBY_DOMAIN']
  )
end

Auth0::Client.new will see that you did not pass in a token and that there is a client_secret available and make a call to oauth/token to retrieve an API token for your Application. This will require that:

  • the Application has "Client Credentials" selected in the Applications > Your app > Show Advanced Settings > Grant Types tab.
  • the Application is authorized for the API in the APIs > Auth0 Management API > Machine to Machine Applications tab with scopes set to the Management API actions you want to perform.

You can also use the method directly for other APIs:

require 'auth0'
auth0_client = Auth0::Client.new(
  client_id: ENV['AUTH0_RUBY_CLIENT_ID'],
  client_secret: ENV['AUTH0_RUBY_CLIENT_SECRET'],
  domain: ENV['AUTH0_RUBY_DOMAIN'],
)
token_result = auth0_client.api_token('your-audience-goes-here')
abort token_result.inspect

Please note: the API token should only be fetched once and cached securely for re-use before the expiration time. Each call to api_token or instantiation of Auth0::Client.new will make an HTTP call to get a new token.

Closes #86

@joshcanhelp joshcanhelp added this to the v4-Next milestone Sep 14, 2018
@joshcanhelp joshcanhelp requested a review from machuga September 17, 2018 16:12
Copy link

@machuga machuga left a comment

Choose a reason for hiding this comment

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

Leaving a few comments before we chat on this on Friday.

client_secret: @client_secret,
audience: audience
}
post('/oauth/token', request_params)
Copy link

Choose a reason for hiding this comment

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

What kind of errors can be raised from this method?

Copy link

Choose a reason for hiding this comment

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

Any reason the request params aren't inlined into the method call?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What kind of errors can be raised from this method?

Not totally sure. Is it important to list them? It uses these under the hood:

https://github.com/rest-client/rest-client which uses:
https://ruby-doc.org/stdlib-2.5.1/libdoc/net/http/rdoc/Net/HTTP.html

Any reason the request params aren't inlined into the method call?

None of them except audience need to be set. Also, just following the example of the rest of the methods here. Would that look like:

def api_token(
  client_id: @client_id,
  client_secret: @client_secret,
  audience: "https://#{@domain}/api/v2/"
)
  request_params = {
    grant_type: 'client_credentials',
    client_id: client_id,
    client_secret: client_secret,
    audience: audience
  }
  post('/oauth/token', request_params)
end

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pushing that change, would like to go this direction in general and need to start somewhere.

client_secret: client_secret,
audience: audience
}
post('/oauth/token', request_params)
Copy link

Choose a reason for hiding this comment

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

Each error type doesn't need accounted for by name, but it's up to you whether you'd like to catch errors here and return a single custom one or two.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Though I think that's probably a good idea at some point, it's a breaking change to add that to all methods here and I don't want this to be any different than the others in that respect. I'll keep that in mind for the next major.

@ambethia
Copy link

Really looking forward to this PR!

@joshcanhelp joshcanhelp force-pushed the add-client-credentials-grant branch from ee6e9bd to f245673 Compare September 25, 2018 21:19
@joshcanhelp joshcanhelp force-pushed the add-client-credentials-grant branch from f245673 to 5fc1f4a Compare September 25, 2018 22:02
Copy link

@machuga machuga left a comment

Choose a reason for hiding this comment

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

LGTM pending passing build

@joshcanhelp joshcanhelp merged commit d245f69 into master Sep 28, 2018
@joshcanhelp joshcanhelp deleted the add-client-credentials-grant branch September 28, 2018 21:51
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.

3 participants