-
-
Notifications
You must be signed in to change notification settings - Fork 622
Basic usage
OAuth client authorization comes in 2 phases: generating authorize URL and exchanges the authorization code for an access token.
require 'oauth2' client = OAuth2::Client.new('client_id', 'client_secret', site: 'https://example.org') # => #<OAuth2::Client: @id="client_id", @secret="client_secret", @site="https://example.org", @options={:authorize_url=>"/oauth/authorize", :token_url=>"/oauth/token", :token_method=>:post, :auth_scheme=>:request_body, :connection_opts=>{}, :connection_build=>nil, :max_redirects=>5, :raise_errors=>true}> # Generate authorize URL. User need follow this URL to authiorize client. client.auth_code.authorize_url(redirect_uri: 'http://localhost:8080/oauth2/callback') # => "https://example.org/oauth/authorize?client_id=client_id&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Foauth2%2Fcallback&response_type=code" # Callback processing from :redirect_uri. Once authorized, an 'authorization_code_value' will returned to exchange for access token token = client.auth_code.get_token('authorization_code_value', redirect_uri: 'http://localhost:8080/oauth2/callback', headers: {'Authorization' => 'Basic some_password'})
Once access token is received. We could use it to get resources by scopes requesed. Using token request helpers.
response = token.get('/api/resource', params: { 'query_foo' => 'bar' } headers: {'Content-type': 'application/json'}) # => #<OAuth2::Response: ...> # Get raw body response.body # => "{\"attribute1\":\"value1\",\"attribute2\":\"value2\"}" # Or parsed content, depends on content type response.parsed # => {"attribute1"=>"value1", "attribute2"=>"value2"}
For more flexible, we could get token and use Faraday or any HTTP client to perform request. But we must handle error response and parse content manually.
response = Faraday.get('https://api.example.org/api/resource', { 'query_foo' => 'bar' }, { 'Content-type': 'application/json', 'Authorization': "Bearer #{token.token}" }) # Then manually parse response body data = JSON.parse(response.body)
Access token could be stored and restored to avoid keep asking user's authorization. oauth2
provides OAuth2::AccessToken#to_hash
and OAuth2::AccessToken.from_hash
to serialize and deserialize access token to hash of string values. We could store to any storage engine like Redis cache or database.
Depends on OAuth provider, refresh token may included, so we could check and/or refresh if access token expired.
token_hash = token.to_hash # => {"token_type"=>"Bearer", "scope"=>"...", "ext_expires_in"=>"3599", "expires_on"=>"1594034747", "not_before"=>"1593948375", "resource"=>"...", "pwd_exp"=>"0", :access_token=>"...", :expires_at=>1594034747} token = OAuth2::AccessToken.from_hash(client, token_hash) # => #<OAuth2::AccessToken: ... > if token.expired? token = token.refresh! end # response = token.get(...)
If it's failed to refresh or no refresh token provided, we need to ask user to reauthorize.