Class: Basecamp::OauthService
- Inherits:
-
Object
- Object
- Basecamp::OauthService
- Defined in:
- app/services/basecamp/oauth_service.rb
Overview
Handles Basecamp 4 OAuth 2.0 token exchange and refresh.
Basecamp uses standard OAuth 2.0 Authorization Code flow:
- Redirect user to authorization_url
- Basecamp redirects back with ?code=...
- Exchange code for access_token + refresh_token
- When token expires, use refresh_token to get a new pair
Reference: https://github.com/basecamp/api/blob/master/sections/authentication.md
Defined Under Namespace
Classes: TokenRefreshError
Constant Summary collapse
- AUTHORIZE_URL =
URL for authorize.
'https://launchpad.37signals.com/authorization/new'- TOKEN_URL =
URL for token.
'https://launchpad.37signals.com/authorization/token'- SITE_URL =
URL for site.
'https://launchpad.37signals.com'- PROVIDER =
Provider.
'basecamp'
Instance Method Summary collapse
-
#access_token! ⇒ String
Get a valid access token, refreshing if expired.
-
#account_id ⇒ String
The configured Basecamp account ID for API calls.
-
#authorization_url(state: nil) ⇒ String
URL to redirect the user to for authorization.
-
#connected? ⇒ Boolean
Whether this CRM account has a stored Basecamp credential.
-
#disconnect! ⇒ Object
Remove the stored credential for this account (disconnect).
-
#exchange_code!(code) ⇒ OauthCredential
Exchange the authorization code for tokens and persist them.
-
#initialize(account: nil) ⇒ OauthService
constructor
A new instance of OauthService.
-
#refresh! ⇒ OauthCredential
Refresh the stored access token.
Constructor Details
#initialize(account: nil) ⇒ OauthService
Returns a new instance of OauthService.
29 30 31 32 33 34 35 |
# File 'app/services/basecamp/oauth_service.rb', line 29 def initialize(account: nil) @account = account @client_id = Heatwave::Configuration.fetch(:basecamp, :client_id) @client_secret = Heatwave::Configuration.fetch(:basecamp, :client_secret) @redirect_url = Heatwave::Configuration.fetch(:basecamp, :redirect_url) @basecamp_account_id = Heatwave::Configuration.fetch(:basecamp, :account_id) end |
Instance Method Details
#access_token! ⇒ String
Get a valid access token, refreshing if expired.
92 93 94 95 96 97 98 |
# File 'app/services/basecamp/oauth_service.rb', line 92 def access_token! credential = OauthCredential.for(PROVIDER, account: @account) raise TokenRefreshError, 'No Basecamp credential found' unless credential refresh! if credential.token_expired? credential.reload.access_token end |
#account_id ⇒ String
The configured Basecamp account ID for API calls.
102 103 104 |
# File 'app/services/basecamp/oauth_service.rb', line 102 def account_id @basecamp_account_id end |
#authorization_url(state: nil) ⇒ String
URL to redirect the user to for authorization.
Uses standard OAuth 2.0 response_type per Basecamp API docs.
41 42 43 44 45 46 47 48 49 |
# File 'app/services/basecamp/oauth_service.rb', line 41 def (state: nil) params = { response_type: 'code', client_id: @client_id, redirect_uri: @redirect_url } params[:state] = state if state.present? "#{AUTHORIZE_URL}?#{params.to_query}" end |
#connected? ⇒ Boolean
Whether this CRM account has a stored Basecamp credential.
108 109 110 |
# File 'app/services/basecamp/oauth_service.rb', line 108 def connected? OauthCredential.for(PROVIDER, account: @account).present? end |
#disconnect! ⇒ Object
Remove the stored credential for this account (disconnect).
113 114 115 |
# File 'app/services/basecamp/oauth_service.rb', line 113 def disconnect! OauthCredential.destroy_by(provider: PROVIDER, account_id: @account&.id) end |
#exchange_code!(code) ⇒ OauthCredential
Exchange the authorization code for tokens and persist them.
54 55 56 57 58 59 60 61 62 63 64 |
# File 'app/services/basecamp/oauth_service.rb', line 54 def exchange_code!(code) response = token_request( grant_type: 'authorization_code', code: code, redirect_uri: @redirect_url, client_id: @client_id, client_secret: @client_secret ) persist_tokens!(response) end |
#refresh! ⇒ OauthCredential
Refresh the stored access token.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'app/services/basecamp/oauth_service.rb', line 69 def refresh! credential = OauthCredential.for(PROVIDER, account: @account) raise TokenRefreshError, 'No Basecamp credential found' unless credential raise TokenRefreshError, 'No refresh token available' if credential.refresh_token.blank? response = token_request( grant_type: 'refresh_token', refresh_token: credential.refresh_token, client_id: @client_id, client_secret: @client_secret ) attrs = { access_token: response['access_token'], expires_at: response['expires_in'] ? response['expires_in'].to_i.seconds.from_now : nil } attrs[:refresh_token] = response['refresh_token'] if response['refresh_token'].present? credential.update!(attrs) credential end |