Class: OmniAuth::Strategies::Himari

Inherits:
OAuth2
  • Object
show all
Defined in:
lib/omniauth/strategies/himari.rb

Defined Under Namespace

Classes: AccessToken, ConfigurationError, IdToken, IdTokenMissing, VerificationError

Instance Method Summary collapse

Instance Method Details

#authorize_paramsObject



121
122
123
124
125
# File 'lib/omniauth/strategies/himari.rb', line 121

def authorize_params
  super.tap do |params|
    params[:scope] = 'openid'
  end
end

#callback_urlObject



113
114
115
# File 'lib/omniauth/strategies/himari.rb', line 113

def callback_url
  options[:redirect_uri] || (full_host + callback_path) # https://github.com/omniauth/omniauth-oauth2/pull/142
end

#clientObject

Raises:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/omniauth/strategies/himari.rb', line 31

def client
  options.client_options.site ||= options.site
  options.client_options.authorize_url ||= '/oidc/authorize'
  options.client_options.token_url ||= '/public/oidc/token'
  options.client_options.userinfo_url ||= '/public/oidc/userinfo'
  options.client_options.access_token_class ||= AccessToken # https://gitlab.com/oauth-xx/oauth2/-/issues/628

  options.client_options.connection_opts ||= {}
  options.client_options.connection_opts[:headers] ||= {}
  options.client_options.connection_opts[:headers] = {
    'User-Agent' => user_agent,
  }.merge(options.client_options.connection_opts[:headers])

  raise ConfigurationError, "client_id and client_secret is required" unless options.client_id && options.client_secret
  raise ConfigurationError, "site is required" unless options.client_options.site
  super
end

#faradayObject



106
107
108
109
110
111
# File 'lib/omniauth/strategies/himari.rb', line 106

def faraday
  @faraday ||= Faraday.new(options.site, headers: {'User-Agent' => user_agent}) do |b|
    b.response :json
    b.response :raise_error
  end
end

#id_tokenObject



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/omniauth/strategies/himari.rb', line 129

def id_token
  @id_token ||= begin
    jwt = access_token.params['id_token'] or raise(IdTokenMissing, 'id_token is missing')
    retval = IdToken.new(*JWT.decode(
      jwt,
      nil,
      true,
      {
        algorithms: jwks.map { |k| k[:alg] }.compact.uniq,
        jwks: jwks,
        verify_aud: true,
        aud: options.client_id,
        verify_iss: true,
        iss: options.site,
        verify_expiration: true,
      }.merge(options.verify_options)
    ))
    verify_at_hash!(retval)
    retval
  end
end

#jwksObject



151
152
153
154
155
# File 'lib/omniauth/strategies/himari.rb', line 151

def jwks
  JWT::JWK::Set.new(jwks_json).tap do |set|
    set.filter! { |k| k[:use] == 'sig' }
  end
end

#jwks_jsonObject



157
158
159
160
161
# File 'lib/omniauth/strategies/himari.rb', line 157

def jwks_json
  faraday.get(options.jwks_url || 'public/jwks').body
rescue Faraday::Error => e
  raise JwksUnavailable, "failed to retrieve jwks; #{e.inspect}"
end

#raw_infoObject



102
103
104
# File 'lib/omniauth/strategies/himari.rb', line 102

def raw_info
  @raw_info ||= (!skip_info? && options.use_userinfo) ? access_token.get('/public/oidc/userinfo').parsed : id_token.claims
end

#user_agentObject



117
118
119
# File 'lib/omniauth/strategies/himari.rb', line 117

def user_agent
  options.user_agent || "OmniauthHimari/#{Omniauth::Himari::VERSION}"
end

#verify_at_hash!(id_token) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/omniauth/strategies/himari.rb', line 81

def verify_at_hash!(id_token)
  return unless options.verify_at_hash

  function = case id_token.header['alg'] # this is safe as we've verified
  when 'ES256', 'RS256'; Digest::SHA256
  when 'ES384'; Digest::SHA384
  when 'ES512'; Digest::SHA512
  else
    raise VerificationError, "unknown hash function to verify at_hash for #{id_token.header['alg']}"
  end

  dgst = function.digest(access_token.token)
  expected_at_hash = Base64.urlsafe_encode64(dgst[0, dgst.size/2], padding: false)

  given_at_hash = id_token.claims['at_hash']

  unless given_at_hash == expected_at_hash
    raise VerificationError, "at_hash mismatch #{given_at_hash.inspect}, #{expected_at_hash.inspect}"
  end
end