# frozen_string_literal: true module PlatformSdk module Identity # Client for making calls to the Identity Server API class Client def initialize(identity_base_url, client_id, client_secret, auth_client = nil) @auth = auth_client.nil? ? AuthClient.new(identity_base_url, client_id, client_secret) : auth_client @conn = Faraday.new(identity_base_url) do |conn| conn.request :authorization, "Bearer", -> { @auth.auth_token } conn.request :retry conn.response :json conn.adapter :net_http end end def with_rescue yield rescue IdentityNotFoundError => e puts e end end # Client for getting auth tokens from identity server class AuthClient attr_accessor :conn, :token def initialize(base_url, client_id, client_secret) @client_id = client_id @client_secret = client_secret @conn = Faraday.new(base_url) do |conn| conn.request :url_encoded conn.response :raise_error conn.response :json conn.adapter :net_http end end def auth_token if expired? response = @conn.post("/connect/token", request_body) @token = response.body.transform_keys(&:to_sym) end @token[:access_token] end def expired? return true if @token.nil? token_expired?(@token[:access_token]) end def token_expired?(jwt) begin expiry_time = jwt_expiry_time(jwt) rescue JWT::ExpiredSignature return true end expiry_time <= Time.now.utc + 45 end def jwt_expiry_time(jwt) Time.at(JWT.decode(jwt, nil, false)[0]["exp"]) end def refresh_token(jwt:, refresh_token:) raise ArgumentError if refresh_token.nil? || jwt.nil? return unless token_expired?(jwt) response = @conn.post("/connect/token", request_body( grant_type: "refresh_token", refresh_token:)) response.body.transform_keys!(&:to_sym) end def refresh_session(session: {}) raise ArgumentError if session[:access_token].nil? || session[:refresh_token].nil? refreshed_tokens = refresh_token(jwt: session[:access_token], refresh_token: session[:refresh_token]) return if refreshed_tokens.nil? session[:id_token] = refreshed_tokens[:id_token] session[:access_token] = refreshed_tokens[:access_token] session[:refresh_token] = refreshed_tokens[:refresh_token] end private def request_body(grant_type: "client_credentials", refresh_token: nil) return { grant_type:, client_id: @client_id, client_secret: @client_secret } if refresh_token.nil? { grant_type:, client_id: @client_id, client_secret: @client_secret, refresh_token: } end end end end