Class: CF::UAA::TokenIssuer
- Inherits:
-
Object
- Object
- CF::UAA::TokenIssuer
- Includes:
- Http
- Defined in:
- lib/uaa/token_issuer.rb
Overview
Client Apps that want to get access to resource servers on behalf of their users need to get tokens via authcode and implicit flows, request scopes, etc., but they don't need to process tokens. This class is for these use cases.
In general most of this class is an implementation of the client pieces of the OAuth2 protocol. See http://tools.ietf.org/html/rfc6749
Constant Summary
Constants included from Http
Http::FORM_UTF8, Http::JSON_UTF8
Instance Method Summary collapse
-
#authcode_grant(authcode_uri, callback_query) ⇒ TokenInfo
Uses the instance client credentials in addition to
callback_queryto get a token via the authorization code grant. -
#authcode_uri(redirect_uri, scope = nil) ⇒ String
Constructs a uri that the client is to return to the browser to direct the user to the authorization server to get an authcode.
-
#autologin_uri(redirect_uri, credentials, scope = nil) ⇒ String
A UAA extension to OAuth2 that allows a client to pre-authenticate a user at the start of an authorization code flow.
-
#client_credentials_grant(scope = nil, client_assertion = nil) ⇒ TokenInfo
Uses the instance client credentials to get a token with a client credentials grant.
-
#get_challenge ⇒ Object
Calculates the challenge from code_verifier.
-
#get_verifier ⇒ Object
Generates a random verifier for PKCE usage.
-
#implicit_grant(implicit_uri, callback_fragment) ⇒ TokenInfo
Gets a token via an implicit grant.
-
#implicit_grant_with_creds(credentials, scope = nil) ⇒ TokenInfo
Gets an access token in a single call to the UAA with the user credentials used for authentication.
-
#implicit_uri(redirect_uri, scope = nil) ⇒ String
Constructs a uri that the client is to return to the browser to direct the user to the authorization server to get an authcode.
-
#initialize(target, client_id, client_secret = nil, options = {}) ⇒ TokenIssuer
constructor
A new instance of TokenIssuer.
-
#jwt_bearer_grant(assertion, scope = nil, client_assertion = nil) ⇒ TokenInfo
Gets an access token with the user assertion used for authentication via the jwt bearer authorization grant.
-
#owner_password_credentials_grant(credentials) ⇒ TokenInfo
Gets an access token with the user credentials used for authentication via the owner password grant.
-
#owner_password_grant(username, password, scope = nil) ⇒ TokenInfo
Uses the instance client credentials in addition to the
usernameandpasswordto get a token via the owner password grant. -
#passcode_grant(passcode, scope = nil) ⇒ TokenInfo
Uses a one-time passcode obtained from the UAA to get a token.
-
#prompts ⇒ Hash
Allows an app to discover what credentials are required for #implicit_grant_with_creds.
-
#refresh_token_grant(refresh_token, scope = nil) ⇒ TokenInfo
Uses the instance client credentials and the given
refresh_tokento get a new access token.
Methods included from Http
basic_auth, #initialize_http_options, #logger, #logger=, #set_request_handler, #trace?
Constructor Details
#initialize(target, client_id, client_secret = nil, options = {}) ⇒ TokenIssuer
Returns a new instance of TokenIssuer.
136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/uaa/token_issuer.rb', line 136 def initialize(target, client_id, client_secret = nil, = {}) @target, @client_id, @client_secret = target, client_id, client_secret @client_assertion = [:client_assertion] || nil @token_target = [:token_target] || target @key_style = [:symbolize_keys] ? :sym : nil @basic_auth = [:basic_auth] == true ? true : false @client_auth_method = [:client_auth_method] || 'client_secret_basic' @code_verifier = [:code_verifier] || nil if @code_verifier.nil? && [:use_pkce] && [:use_pkce] == true @code_verifier = get_verifier end () end |
Instance Method Details
#authcode_grant(authcode_uri, callback_query) ⇒ TokenInfo
Uses the instance client credentials in addition to callback_query
to get a token via the authorization code grant.
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/uaa/token_issuer.rb', line 254 def authcode_grant(authcode_uri, callback_query) ac_params = Util.decode_form(URI.parse(authcode_uri).query) unless ac_params['state'] && ac_params['redirect_uri'] raise ArgumentError, "authcode redirect must happen before authcode grant" end begin params = Util.decode_form(callback_query) authcode = params['code'] raise BadResponse unless params['state'] == ac_params['state'] && authcode rescue URI::InvalidURIError, ArgumentError, BadResponse raise BadResponse, "received invalid response from target #{@target}" end if not @code_verifier.nil? request_token(grant_type: 'authorization_code', code: authcode, redirect_uri: ac_params['redirect_uri'], code_verifier: @code_verifier) else request_token(grant_type: 'authorization_code', code: authcode, redirect_uri: ac_params['redirect_uri']) end end |
#authcode_uri(redirect_uri, scope = nil) ⇒ String
Constructs a uri that the client is to return to the browser to direct the user to the authorization server to get an authcode.
240 241 242 |
# File 'lib/uaa/token_issuer.rb', line 240 def authcode_uri(redirect_uri, scope = nil) @target + ('code', redirect_uri, scope) end |
#autologin_uri(redirect_uri, credentials, scope = nil) ⇒ String
A UAA extension to OAuth2 that allows a client to pre-authenticate a user at the start of an authorization code flow. By passing in the user's credentials the server can establish a session with the user's browser without reprompting for authentication. This is useful for user account management apps so that they can create a user account, or reset a password for the user, without requiring the user to type in their credentials again.
225 226 227 228 229 230 231 232 233 |
# File 'lib/uaa/token_issuer.rb', line 225 def autologin_uri(redirect_uri, credentials, scope = nil) headers = {'content-type' => FORM_UTF8, 'accept' => JSON_UTF8, 'authorization' => Http.basic_auth(@client_id, @client_secret) } body = Util.encode_form(credentials) reply = json_parse_reply(nil, *request(@target, :post, "/autologin", body, headers)) raise BadResponse, "no autologin code in reply" unless reply['code'] @target + ('code', redirect_uri, scope, random_state, code: reply['code']) end |
#client_credentials_grant(scope = nil, client_assertion = nil) ⇒ TokenInfo
Uses the instance client credentials to get a token with a client credentials grant. See http://tools.ietf.org/html/rfc6749#section-4.4
320 321 322 |
# File 'lib/uaa/token_issuer.rb', line 320 def client_credentials_grant(scope = nil, client_assertion = nil) request_token(grant_type: 'client_credentials', scope: scope, client_assertion: client_assertion) end |
#get_challenge ⇒ Object
Calculates the challenge from code_verifier
285 286 287 |
# File 'lib/uaa/token_issuer.rb', line 285 def get_challenge @challenge ||= Digest::SHA256.base64digest(get_verifier).tr("+/", "-_").tr("=", "") end |
#get_verifier ⇒ Object
Generates a random verifier for PKCE usage
276 277 278 279 280 281 282 |
# File 'lib/uaa/token_issuer.rb', line 276 def get_verifier if not @code_verifier.nil? @verifier = @code_verifier else @verifier ||= SecureRandom.base64(96).tr("+/", "-_").tr("=", "") end end |
#implicit_grant(implicit_uri, callback_fragment) ⇒ TokenInfo
Gets a token via an implicit grant.
207 208 209 210 211 212 213 |
# File 'lib/uaa/token_issuer.rb', line 207 def implicit_grant(implicit_uri, callback_fragment) in_params = Util.decode_form(URI.parse(implicit_uri).query) unless in_params['state'] && in_params['redirect_uri'] raise ArgumentError, "redirect must happen before implicit grant" end parse_implicit_params(callback_fragment, in_params['state']) end |
#implicit_grant_with_creds(credentials, scope = nil) ⇒ TokenInfo
Gets an access token in a single call to the UAA with the user credentials used for authentication.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/uaa/token_issuer.rb', line 166 def implicit_grant_with_creds(credentials, scope = nil) # this manufactured redirect_uri is a convention here, not part of OAuth2 redir_uri = "https://uaa.cloudfoundry.com/redirect/#{@client_id}" response_type = "token" response_type = "#{response_type} id_token" if scope && (scope.include? "openid") uri = (response_type, redir_uri, scope, state = random_state) # the accept header is only here so the uaa will issue error replies in json to aid debugging headers = {'content-type' => FORM_UTF8, 'accept' => JSON_UTF8 } body = Util.encode_form(credentials.merge(source: 'credentials')) status, body, headers = request(@target, :post, uri, body, headers) raise BadResponse, "status #{status}" unless status == 302 req_uri, reply_uri = URI.parse(redir_uri), URI.parse(headers['location']) fragment, reply_uri.fragment = reply_uri.fragment, nil raise BadResponse, "bad location header" unless req_uri == reply_uri parse_implicit_params(fragment, state) rescue URI::Error => e raise BadResponse, "bad location header in reply: #{e.}" end |
#implicit_uri(redirect_uri, scope = nil) ⇒ String
Constructs a uri that the client is to return to the browser to direct the user to the authorization server to get an authcode.
190 191 192 193 194 |
# File 'lib/uaa/token_issuer.rb', line 190 def implicit_uri(redirect_uri, scope = nil) response_type = "token" response_type = "#{response_type} id_token" if scope && (scope.include? "openid") @target + (response_type, redirect_uri, scope) end |
#jwt_bearer_grant(assertion, scope = nil, client_assertion = nil) ⇒ TokenInfo
Gets an access token with the user assertion used for authentication via the jwt bearer authorization grant. See http://tools.ietf.org/html/rfc7523#section-2.1.
336 337 338 |
# File 'lib/uaa/token_issuer.rb', line 336 def jwt_bearer_grant(assertion, scope = nil, client_assertion = nil) request_token(grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: assertion, scope: scope, client_assertion: client_assertion) end |
#owner_password_credentials_grant(credentials) ⇒ TokenInfo
Gets an access token with the user credentials used for authentication via the owner password grant. See http://tools.ietf.org/html/rfc6749#section-4.3.
312 313 314 315 |
# File 'lib/uaa/token_issuer.rb', line 312 def owner_password_credentials_grant(credentials) credentials[:grant_type] = 'password' request_token(credentials) end |
#owner_password_grant(username, password, scope = nil) ⇒ TokenInfo
Uses the instance client credentials in addition to the username
and password to get a token via the owner password grant.
See http://tools.ietf.org/html/rfc6749#section-4.3.
293 294 295 296 |
# File 'lib/uaa/token_issuer.rb', line 293 def owner_password_grant(username, password, scope = nil) request_token(grant_type: 'password', username: username, password: password, scope: scope) end |
#passcode_grant(passcode, scope = nil) ⇒ TokenInfo
Uses a one-time passcode obtained from the UAA to get a token.
301 302 303 |
# File 'lib/uaa/token_issuer.rb', line 301 def passcode_grant(passcode, scope = nil) request_token(grant_type: 'password', passcode: passcode, scope: scope) end |
#prompts ⇒ Hash
Allows an app to discover what credentials are required for #implicit_grant_with_creds.
154 155 156 157 158 |
# File 'lib/uaa/token_issuer.rb', line 154 def prompts reply = json_get(@target, '/login') return reply[jkey :prompts] if reply && reply[jkey :prompts] raise BadResponse, "No prompts in response from target #{@target}" end |
#refresh_token_grant(refresh_token, scope = nil) ⇒ TokenInfo
Uses the instance client credentials and the given refresh_token to get
a new access token. See http://tools.ietf.org/html/rfc6749#section-6
327 328 329 |
# File 'lib/uaa/token_issuer.rb', line 327 def refresh_token_grant(refresh_token, scope = nil) request_token(grant_type: 'refresh_token', refresh_token: refresh_token, scope: scope) end |