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 =
'zoom'- TOKEN_URL =
'https://zoom.us/oauth/token'- 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.
22 23 24 25 26 |
# File 'app/services/zoom/oauth_service.rb', line 22 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.
75 76 77 78 79 80 81 |
# File 'app/services/zoom/oauth_service.rb', line 75 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.
85 86 87 |
# File 'app/services/zoom/oauth_service.rb', line 85 def connected? OauthCredential.for(PROVIDER, account: @account).present? end |
#disconnect! ⇒ Object
Remove the stored credential (disconnect).
90 91 92 |
# File 'app/services/zoom/oauth_service.rb', line 90 def disconnect! OauthCredential.where(provider: PROVIDER, account_id: @account.id).destroy_all end |
#healthy? ⇒ Boolean
Verify the current token is valid by calling Zoom API.
Attempts refresh first if token is expired.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'app/services/zoom/oauth_service.rb', line 97 def healthy? credential = OauthCredential.for(PROVIDER, account: @account) return false unless credential&.access_token.present? 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.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'app/services/zoom/oauth_service.rb', line 44 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 unless response.status == 200 raise TokenRefreshError, "Token refresh failed (#{response.status}): #{response.body}" end 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.
31 32 33 34 35 36 37 38 39 |
# File 'app/services/zoom/oauth_service.rb', line 31 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.at(credentials['expires_at']) : 1.hour.from_now cred.token_type = 'Bearer' cred.save! cred end |