Class: Zoom::OauthService
- Inherits:
-
Object
- Object
- Zoom::OauthService
- Defined in:
- app/services/zoom/oauth_service.rb
Overview
Handles Zoom OAuth 2.0 token storage and refresh via OauthCredential.
Zoom uses standard OAuth 2.0 Authorization Code flow:
- User authorizes via OmniAuth (Devise)
- Callback stores tokens in OauthCredential
- When token expires (1 hour), refresh_token is used to get a new pair
- Refresh tokens expire after 90 days of non-use
Reference: https://developers.zoom.us/docs/integrations/oauth/
Defined Under Namespace
Classes: TokenRefreshError
Constant Summary collapse
- PROVIDER =
Provider.
'zoom'- TOKEN_URL =
URL for token.
'https://zoom.us/oauth/token'- API_BASE =
Api base.
'https://api.zoom.us/v2'
Instance Method Summary collapse
-
#access_token! ⇒ String
Get a valid access token, refreshing if expired.
-
#connected? ⇒ Boolean
Whether this account has a stored Zoom credential.
-
#disconnect! ⇒ Object
Remove the stored credential (disconnect).
-
#healthy? ⇒ Boolean
Verify the current token is valid by calling Zoom API.
-
#initialize(account:) ⇒ OauthService
constructor
A new instance of OauthService.
-
#refresh! ⇒ OauthCredential
Refresh the stored access token.
-
#store_from_omniauth!(credentials) ⇒ OauthCredential
Store tokens from OmniAuth callback.
Constructor Details
#initialize(account:) ⇒ OauthService
Returns a new instance of OauthService.
27 28 29 30 31 |
# File 'app/services/zoom/oauth_service.rb', line 27 def initialize(account:) @account = account @client_id = Heatwave::Configuration.fetch(:zoom, :client_id) @client_secret = Heatwave::Configuration.fetch(:zoom, :client_secret) end |
Instance Method Details
#access_token! ⇒ String
Get a valid access token, refreshing if expired.
78 79 80 81 82 83 84 |
# File 'app/services/zoom/oauth_service.rb', line 78 def access_token! credential = OauthCredential.for(PROVIDER, account: @account) raise TokenRefreshError, 'No Zoom credential found' unless credential refresh! if credential.token_expired? credential.reload.access_token end |
#connected? ⇒ Boolean
Whether this account has a stored Zoom credential.
88 89 90 |
# File 'app/services/zoom/oauth_service.rb', line 88 def connected? OauthCredential.for(PROVIDER, account: @account).present? end |
#disconnect! ⇒ Object
Remove the stored credential (disconnect).
93 94 95 |
# File 'app/services/zoom/oauth_service.rb', line 93 def disconnect! OauthCredential.destroy_by(provider: PROVIDER, account_id: @account.id) end |
#healthy? ⇒ Boolean
Verify the current token is valid by calling Zoom API.
Attempts refresh first if token is expired.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'app/services/zoom/oauth_service.rb', line 100 def healthy? credential = OauthCredential.for(PROVIDER, account: @account) return false if credential&.access_token.blank? refresh! if credential.token_expired? credential.reload response = connection.get("#{API_BASE}/users/me") do |req| req.headers['Authorization'] = "Bearer #{credential.access_token}" end response.status == 200 rescue TokenRefreshError, StandardError => e Rails.logger.error("[Zoom::OauthService] Health check failed for account #{@account.id}: #{e.}") false end |
#refresh! ⇒ OauthCredential
Refresh the stored access token.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'app/services/zoom/oauth_service.rb', line 49 def refresh! credential = OauthCredential.for(PROVIDER, account: @account) raise TokenRefreshError, 'No Zoom credential found' unless credential raise TokenRefreshError, 'No refresh token available' if credential.refresh_token.blank? encoded = Base64.strict_encode64("#{@client_id}:#{@client_secret}") response = connection.post(TOKEN_URL) do |req| req.headers['Authorization'] = "Basic #{encoded}" req.headers['Content-Type'] = 'application/x-www-form-urlencoded' req.body = URI.encode_www_form( grant_type: 'refresh_token', refresh_token: credential.refresh_token ) end raise TokenRefreshError, "Token refresh failed (#{response.status}): #{response.body}" unless response.status == 200 data = JSON.parse(response.body) credential.update!( access_token: data['access_token'], refresh_token: data['refresh_token'].presence || credential.refresh_token, expires_at: data['expires_in'] ? data['expires_in'].to_i.seconds.from_now : 1.hour.from_now ) credential end |
#store_from_omniauth!(credentials) ⇒ OauthCredential
Store tokens from OmniAuth callback.
36 37 38 39 40 41 42 43 44 |
# File 'app/services/zoom/oauth_service.rb', line 36 def store_from_omniauth!(credentials) cred = OauthCredential.find_or_initialize_by(provider: PROVIDER, account_id: @account.id) cred.access_token = credentials['token'] cred.refresh_token = credentials['refresh_token'] if credentials['refresh_token'].present? cred.expires_at = credentials['expires_at'] ? Time.zone.at(credentials['expires_at']) : 1.hour.from_now cred.token_type = 'Bearer' cred.save! cred end |