# frozen_string_literal: true require "uri" require "faraday" module Fiken # OAuth2 authorization-code helper. # # oauth = Fiken::OAuth.new(client_id:, client_secret:, redirect_uri:) # redirect_to oauth.authorize_url(state: "abc") # token = oauth.exchange_code(params[:code]) # client = Fiken::Client.new(access_token: token.access_token) # refreshed = oauth.refresh(token.refresh_token) class OAuth AUTHORIZE_URL = "https://fiken.no/oauth/authorize" TOKEN_URL = "https://fiken.no/oauth/token" attr_reader :client_id, :client_secret, :redirect_uri def initialize(client_id:, client_secret:, redirect_uri: nil) @client_id = client_id @client_secret = client_secret @redirect_uri = redirect_uri end # Build the URL to send the user to in order to authorize the app. def authorize_url(state:, redirect_uri: self.redirect_uri, scope: nil) params = { response_type: "code", client_id: client_id, redirect_uri: redirect_uri, state: state, scope: scope }.compact "#{AUTHORIZE_URL}?#{URI.encode_www_form(params)}" end # Exchange the authorization code from the callback for tokens. def exchange_code(code, redirect_uri: self.redirect_uri) token_request(grant_type: "authorization_code", code: code, redirect_uri: redirect_uri) end # Use a refresh token to obtain a fresh access token. def refresh(refresh_token) token_request(grant_type: "refresh_token", refresh_token: refresh_token) end private def token_request(params) response = token_connection.post(TOKEN_URL, params.compact) raise Error.from_response(response.status, response.body) if response.status >= 400 Object.new(response.body) end def token_connection @token_connection ||= Faraday.new do |f| f.request :url_encoded f.request :authorization, :basic, client_id, client_secret f.response :json, content_type: /\bjson$/ f.adapter Faraday.default_adapter end end end end