class OmniAuth::Strategies::OpenIDConnect

Constants

RESPONSE_TYPE_EXCEPTIONS

Public Instance Methods

authorization_code() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 146
def authorization_code
  params['code']
end
authorize_uri() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 158
def authorize_uri
  client.redirect_uri = redirect_uri
  opts = {
    response_type: options.response_type,
    response_mode: options.response_mode,
    scope: options.scope,
    state: new_state,
    login_hint: params['login_hint'],
    ui_locales: params['ui_locales'],
    claims_locales: params['claims_locales'],
    prompt: options.prompt,
    nonce: (new_nonce if options.send_nonce),
    hd: options.hd,
    acr_values: options.acr_values,
  }

  opts.merge!(options.extra_authorize_params) unless options.extra_authorize_params.empty?

  client.authorization_uri(opts.reject { |_k, v| v.nil? })
end
callback_phase() click to toggle source
Calls superclass method
# File lib/omniauth/strategies/openid_connect.rb, line 106
def callback_phase
  error = params['error_reason'] || params['error']
  error_description = params['error_description'] || params['error_reason']
  invalid_state = params['state'].to_s.empty? || params['state'] != stored_state

  raise CallbackError, error: params['error'], reason: error_description, uri: params['error_uri'] if error
  raise CallbackError, error: :csrf_detected, reason: "Invalid 'state' parameter" if invalid_state

  return unless valid_response_type?

  options.issuer = issuer if options.issuer.nil? || options.issuer.empty?

  verify_id_token!(params['id_token']) if configured_response_type == 'id_token'
  discover!
  client.redirect_uri = redirect_uri

  return id_token_callback_phase if configured_response_type == 'id_token'

  client.authorization_code = authorization_code
  access_token
  super
rescue CallbackError => e
  fail!(e.error, e)
rescue ::Rack::OAuth2::Client::Error => e
  fail!(e.response[:error], e)
rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
  fail!(:timeout, e)
rescue ::SocketError => e
  fail!(:failed_to_connect, e)
end
client() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 92
def client
  @client ||= ::OpenIDConnect::Client.new(client_options)
end
config() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 96
def config
  @config ||= ::OpenIDConnect::Discovery::Provider::Config.discover!(options.issuer)
end
end_session_uri() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 150
def end_session_uri
  return unless end_session_endpoint_is_valid?

  end_session_uri = URI(client_options.end_session_endpoint)
  end_session_uri.query = encoded_post_logout_redirect_uri
  end_session_uri.to_s
end
other_phase() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 137
def other_phase
  if logout_path_pattern.match?(current_path)
    options.issuer = issuer if options.issuer.to_s.empty?
    discover!
    return redirect(end_session_uri) if end_session_uri
  end
  call_app!
end
public_key() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 179
def public_key
  return config.jwks if options.discovery

  key_or_secret
end
request_phase() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 100
def request_phase
  options.issuer = issuer if options.issuer.to_s.empty?
  discover!
  redirect authorize_uri
end
uid() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 60
def uid
  user_info.raw_attributes[options.uid_field.to_sym] || user_info.sub
end

Private Instance Methods

access_token() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 215
def access_token
  return @access_token if @access_token

  @access_token = client.access_token!(
    scope: (options.scope if options.send_scope_to_token_endpoint),
    client_auth_method: options.client_auth_method
  )

  verify_id_token!(@access_token.id_token) if configured_response_type == 'code'

  @access_token
end
client_options() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 232
def client_options
  options.client_options
end
configured_response_type() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 336
def configured_response_type
  @configured_response_type ||= options.response_type.to_s
end
decode(str) click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 289
def decode(str)
  UrlSafeBase64.decode64(str).unpack1('B*').to_i(2).to_s
end
decode_id_token(id_token) click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 228
def decode_id_token(id_token)
  ::OpenIDConnect::ResponseObject::IdToken.decode(id_token, public_key)
end
discover!() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 193
def discover!
  return unless options.discovery

  client_options.authorization_endpoint = config.authorization_endpoint
  client_options.token_endpoint = config.token_endpoint
  client_options.userinfo_endpoint = config.userinfo_endpoint
  client_options.jwks_uri = config.jwks_uri
  client_options.end_session_endpoint = config.end_session_endpoint if config.respond_to?(:end_session_endpoint)
end
encoded_post_logout_redirect_uri() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 299
def encoded_post_logout_redirect_uri
  return unless options.post_logout_redirect_uri

  URI.encode_www_form(
    post_logout_redirect_uri: options.post_logout_redirect_uri
  )
end
end_session_endpoint_is_valid?() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 307
def end_session_endpoint_is_valid?
  client_options.end_session_endpoint &&
    client_options.end_session_endpoint =~ URI::DEFAULT_PARSER.make_regexp
end
id_token_callback_phase() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 316
def id_token_callback_phase
  user_data = decode_id_token(params['id_token']).raw_attributes
  env['omniauth.auth'] = AuthHash.new(
    provider: name,
    uid: user_data['sub'],
    info: { name: user_data['name'], email: user_data['email'] },
    extra: { raw_info: user_data }
  )
  call_app!
end
issuer() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 187
def issuer
  resource = "#{ client_options.scheme }://#{ client_options.host }"
  resource = "#{ resource }:#{ client_options.port }" if client_options.port
  ::OpenIDConnect::Discovery::Provider.discover!(resource).issuer
end
key_or_secret() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 265
def key_or_secret
  case options.client_signing_alg
  when :HS256, :HS384, :HS512
    client_options.secret
  when :RS256, :RS384, :RS512
    if options.client_jwk_signing_key
      parse_jwk_key(options.client_jwk_signing_key)
    elsif options.client_x509_signing_key
      parse_x509_key(options.client_x509_signing_key)
    end
  end
end
logout_path_pattern() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 312
def logout_path_pattern
  @logout_path_pattern ||= %r{\A#{Regexp.quote(request_path)}(/logout)}
end
new_nonce() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 251
def new_nonce
  session['omniauth.nonce'] = SecureRandom.hex(16)
end
new_state() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 236
def new_state
  state = if options.state.respond_to?(:call)
            if options.state.arity == 1
              options.state.call(env)
            else
              options.state.call
            end
          end
  session['omniauth.state'] = state || SecureRandom.hex(16)
end
parse_jwk_key(key) click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 282
def parse_jwk_key(key)
  json = JSON.parse(key)
  return JSON::JWK::Set.new(json['keys']) if json.key?('keys')

  JSON::JWK.new(json)
end
parse_x509_key(key) click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 278
def parse_x509_key(key)
  OpenSSL::X509::Certificate.new(key).public_key
end
redirect_uri() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 293
def redirect_uri
  return client_options.redirect_uri unless params['redirect_uri']

  "#{ client_options.redirect_uri }?redirect_uri=#{ CGI.escape(params['redirect_uri']) }"
end
session() click to toggle source
Calls superclass method
# File lib/omniauth/strategies/openid_connect.rb, line 259
def session
  return {} if @env.nil?

  super
end
stored_nonce() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 255
def stored_nonce
  session.delete('omniauth.nonce')
end
stored_state() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 247
def stored_state
  session.delete('omniauth.state')
end
user_info() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 203
def user_info
  return @user_info if @user_info

  if access_token.id_token
    decoded = decode_id_token(access_token.id_token).raw_attributes

    @user_info = ::OpenIDConnect::ResponseObject::UserInfo.new access_token.userinfo!.raw_attributes.merge(decoded)
  else
    @user_info = access_token.userinfo!
  end
end
valid_response_type?() click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 327
def valid_response_type?
  return true if params.key?(configured_response_type)

  error_attrs = RESPONSE_TYPE_EXCEPTIONS[configured_response_type]
  fail!(error_attrs[:key], error_attrs[:exception_class].new(params['error']))

  false
end
verify_id_token!(id_token) click to toggle source
# File lib/omniauth/strategies/openid_connect.rb, line 340
def verify_id_token!(id_token)
  return unless id_token

  decode_id_token(id_token).verify!(issuer: options.issuer,
                                    client_id: client_options.identifier,
                                    nonce: stored_nonce)
end