Skip to content

Invalid JWT token type (invalid_credentials: OAuth2::Error) #157

@dombarnes

Description

@dombarnes

I am currently using this gem in a couple of Rails projects without issue connecting to an IdentityServer with openid/oauth.
I was previously using a fairly basic handwritten Oauth handler in a modular sinatra project and wanted to migrate to this gem to be consistent.
I transferred over my strategy but when I log in now, I hit my oauth server requesting an id_token code method, get back a response with a code. That is then passed to the token endpoint and I get back a response with an id_tokenand an access_token. However when I call access_token.get('connect/userinfo')to get my user info, the HTTP call seems to be using the id_tokennot the access_token and so I am getting a 401 unauthorised error.
I can't seem to figure out what's going wrong.

my_company.rb
# frozen_string_literal: true

require 'omniauth-oauth2'
require 'jwt'
require 'securerandom'

module OmniAuth
  module Strategies
    class MyCompany < OmniAuth::Strategies::OAuth2

      args %i[client_id client_secret client_scope]

      option :name, 'my_company'
      option :client_options, {
        site: ENV.fetch('OAUTH_SERVER'),
        authorize_url: '/connect/authorize',
        redirect_uri: "#{ENV['APPLICATION_HOST']}/auth/my_company/callback",
        token_url: '/connect/token'
      }

      option :authorize_params, {
        nonce: SecureRandom.hex(24),
        scope: ENV.fetch('OAUTH_SCOPE', 'openid profile'),
        response_mode: 'form_post',
        response_type: 'code id_token'
      }

      uid { raw_info['sub'] }

      info do
        {
          email: raw_info['email'],
          displayname: raw_info['displayname'],
          role: raw_info['role']
        }
      end

      extra do
        hash = {}
        hash[:raw_info] = raw_info unless skip_info?
        hash[:id_token] = access_token.token
        if !options[:skip_jwt] && !access_token.token.nil?
          hash[:id_info] = validated_token(access_token.token)
        end
        hash
      end

      def callback_url
        options[:redirect_uri] || (full_host + script_name + callback_path)
      end

      def raw_info
        @raw_info ||= access_token.get('connect/userinfo').parsed
      end

      def authorize_params
        super.merge(nonce: new_nonce)
      end

      alias oauth2_access_token access_token

      def access_token
        ::OAuth2::AccessToken.new(client, oauth2_access_token.token, {
          refresh_token: oauth2_access_token.refresh_token,
          expires_in: oauth2_access_token.expires_in,
          expires_at: oauth2_access_token.expires_at
        })
      end

      private

      def new_nonce
        session['omniauth.nonce'] = SecureRandom.urlsafe_base64(16)
      end

      def stored_nonce
        session.delete('omniauth.nonce')
      end

      def verify_options
        { verify_expiration: true,
          verify_not_before: true,
          verify_iat: true,
          verify_iss: true,
          'iss' => issuer,
          verify_aud: true,
          'aud' => client_id }
      end
    end
  end
end

OmniAuth.config.add_camelization 'my_company', 'MyCompany'

Token response

{"id_token":"my_id_token","access_token":"my_access_token","expires_in":3600,"token_type":"Bearer","refresh_token":"my_refresh_token","scope":"openid profile offline_access"}

As such, its not even hitting my callback URL as Puma is catching the error.

Puma caught this error:  (OAuth2::Error)
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/oauth2-2.0.6/lib/oauth2/client.rb:139:in `request'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/oauth2-2.0.6/lib/oauth2/access_token.rb:140:in `request'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/oauth2-2.0.6/lib/oauth2/access_token.rb:147:in `get'
/Users/myuser/workprojects/myproject/lib/omni_auth/strategies/my_company.rb:55:in `raw_info'
/Users/myuser/workprojects/myproject/lib/omni_auth/strategies/my_company.rb:42:in `block in <class:MyCompany>'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:109:in `instance_eval'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:109:in `block in compile_stack'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:108:in `each'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:108:in `inject'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:108:in `compile_stack'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:102:in `extra_stack'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:387:in `extra'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:392:in `auth_hash'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:417:in `callback_phase'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-oauth2-1.8.0/lib/omniauth/strategies/oauth2.rb:93:in `callback_phase'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:272:in `callback_call'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:194:in `call!'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:169:in `call'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:202:in `call!'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/strategy.rb:169:in `call'
/Users/myuser/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/omniauth-2.1.0/lib/omniauth/builder.rb:44:in `call'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions