Class: OpenIDConnectClient::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/openid_connect_client.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(provider_url = nil, client_id = nil, client_secret = nil) ⇒ Client

Returns a new instance of Client.

Parameters:

  • provider_url (defaults to: nil)

    string optional

  • client_id (defaults to: nil)

    string optional

  • client_secret (defaults to: nil)

    string optional



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/openid_connect_client.rb', line 381

def initialize(provider_url = nil, client_id = nil, client_secret = nil)
    @scopes = Hash.new
    @state = Hash.new
    @state = Hash.new
    @auth_params = Hash.new
    @user_info = Hash.new
    @params = Hash.new
    @response = Hash.new
    
    @client_id = client_id
    @client_secret = client_secret
    @provider_url = provider_url
    
    substitute = "/"
    
    if self.instance_variable_defined? :@provider_url
        @well_known_config_url = provider_url.gsub(/[#{substitute}]+$/, '') + "/.well-known/openid-configuration/"
    end
end

Instance Attribute Details

#access_tokenObject (readonly)

Returns the value of attribute access_token.



372
373
374
# File 'lib/openid_connect_client.rb', line 372

def access_token
  @access_token
end

#auth_endpointObject (readonly)

Returns the value of attribute auth_endpoint.



372
373
374
# File 'lib/openid_connect_client.rb', line 372

def auth_endpoint
  @auth_endpoint
end

#cert_path=(value) ⇒ Object (writeonly)

Sets the attribute cert_path

Parameters:

  • value

    the value to set the attribute cert_path to.



373
374
375
# File 'lib/openid_connect_client.rb', line 373

def cert_path=(value)
  @cert_path = value
end

#client_idObject

Returns the value of attribute client_id.



374
375
376
# File 'lib/openid_connect_client.rb', line 374

def client_id
  @client_id
end

#client_nameObject

Returns the value of attribute client_name.



374
375
376
# File 'lib/openid_connect_client.rb', line 374

def client_name
  @client_name
end

#client_secretObject

Returns the value of attribute client_secret.



374
375
376
# File 'lib/openid_connect_client.rb', line 374

def client_secret
  @client_secret
end

#http_proxy=(value) ⇒ Object (writeonly)

Sets the attribute http_proxy

Parameters:

  • value

    the value to set the attribute http_proxy to.



373
374
375
# File 'lib/openid_connect_client.rb', line 373

def http_proxy=(value)
  @http_proxy = value
end

#params=(value) ⇒ Object (writeonly)

Sets the attribute params

Parameters:

  • value

    the value to set the attribute params to.



373
374
375
# File 'lib/openid_connect_client.rb', line 373

def params=(value)
  @params = value
end

#provider_configObject

Returns the value of attribute provider_config.



374
375
376
# File 'lib/openid_connect_client.rb', line 374

def provider_config
  @provider_config
end

#refresh_tokenObject (readonly)

Returns the value of attribute refresh_token.



372
373
374
# File 'lib/openid_connect_client.rb', line 372

def refresh_token
  @refresh_token
end

#stateObject

Returns the value of attribute state.



374
375
376
# File 'lib/openid_connect_client.rb', line 374

def state
  @state
end

#well_known_config_urlObject

Returns the value of attribute well_known_config_url.



374
375
376
# File 'lib/openid_connect_client.rb', line 374

def well_known_config_url
  @well_known_config_url
end

Instance Method Details

#add_auth_param(hash) ⇒ Object

Returns hash.

Parameters:

  • hash

    hash

Returns:

  • hash



603
604
605
# File 'lib/openid_connect_client.rb', line 603

def add_auth_param(hash)
    @auth_params = @auth_params.merge(hash)
end

#add_provider_config_param(hash) ⇒ Object

Returns hash.

Parameters:

  • hash

    hash

Returns:

  • hash



611
612
613
# File 'lib/openid_connect_client.rb', line 611

def add_provider_config_param(hash)
    @state = @state.merge(hash)
end

#authenticateObject

Gets the access token needed to request user info.

Returns:

  • bool



444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
# File 'lib/openid_connect_client.rb', line 444

def authenticate()
    # Do a preemptive check to see if the provider has raised an error from a previous redirect
    unless @response[:error].nil?
        raise OpenIDConnectClientException, "Error: #{@response[:error]} Description: #{@response[:error_description]}"
    end
    
    # If we have an authorization code then proceed to request a token
    if not @params["code"].nil? || @params["code"].empty?
        code = @params["code"]
        token_endpoint = get_provider_config_value(:token_endpoint)
        grant_type = "authorization_code"
        
        tokemoduluss = {
            grant_type: grant_type,
            code: code,
            redirect_uri: @redirect_url,
            client_id: @client_id,
            client_secret: @client_secret
        }
        
        # Convert token params to string format
        tokemoduluss = http_build_query(tokemoduluss)
        
        token_data = fetch_url(token_endpoint, tokemoduluss).body_str
        
        unless token_data
            raise OpenIDConnectClientException, "Unable to get token data from the provider."
        end
        
        token_json = JSON[token_data]
        
        # Throw an error if the server returns one
        if token_json["error"]
            raise OpenIDConnectClientException, token_json["error_description"]
        end
        
        # Do an OpenID Connect session check
        unless @params["state"] == @state["openid_connect_state"]
            raise OpenIDConnectClientException, "Unable to determine state."
        end
    
        unless token_json["id_token"]
            raise OpenIDConnectClientException, "User did not authorize openid scope."
        end
        
        # Verify the signature
        unless verify_JWT_signature(token_json["id_token"])
            raise OpenIDConnectClientException, "Unable to verify signature."
        end
        
        claims = decode_JWT(token_json["id_token"], 1)
        
        # If this is a valid claim
        unless verify_JWT_claims(claims)
            raise OpenIDConnectClientException, "Unable to verify JWT claims."
        end
        
        # Save the access token
        @access_token = token_json["access_token"]
        
        # Save the refresh token, if we got one
        if token_json["refresh_token"]
            @refresh_token = token_json["refresh_token"]
        end
        
        # Success!
        return true
    end
end

#authorizeObject

Builds the user authentication url.

Returns:

  • void



406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
# File 'lib/openid_connect_client.rb', line 406

def authorize()           
    get_provider_config()
    
    auth_endpoint = get_provider_config_value(:authorization_endpoint)
    response_type = "code"
    
    # Generate and store a nonce in the session
    # The nonce is an arbitrary value
    nonce = random_string()
    @state["openid_connect_nonce"] = nonce
    
    # State essentially acts as a session key for OIDC
    state = random_string()
    @state["openid_connect_state"] = state
    
    @auth_params = @auth_params.merge({
        response_type: response_type,
        redirect_uri: @redirect_url,
        client_id: @client_id,
        nonce: nonce,
        state: state,
        scope: 'openid'
    })
    
    # If the client has been registered with additional scopes
    if @scopes.length > 0
        @auth_params[:scope] = @scopes.join(' ')
        auth_endpoint += '?' + http_build_query(@auth_params)
        @auth_endpoint = auth_endpoint
    end
end

#get(attribute) ⇒ Object

Attribute Type Description user_id string REQUIRED Identifier for the End-User at the Issuer. name string End-User’s full name in displayable form including all name parts, ordered according to End-User’s locale and preferences. given_name string Given name or first name of the End-User. family_name string Surname or last name of the End-User. middle_name string Middle name of the End-User. nickname string Casual name of the End-User that may or may not be the same as the given_name. For instance, a nickname value of Mike might be returned alongside a given_name value of Michael. profile string URL of End-User’s profile page. picture string URL of the End-User’s profile picture. website string URL of End-User’s web page or blog. email string The End-User’s preferred e-mail address. verified boolean True if the End-User’s e-mail address has been verified; otherwise false. gender string The End-User’s gender: Values defined by this specification are female and male. Other values MAY be used when neither of the defined values are applicable. birthday string The End-User’s birthday, represented as a date string in MM/DD/YYYY format. The year MAY be 0000, indicating that it is omitted. zoneinfo string String from zoneinfo [zoneinfo] time zone database. For example, Europe/Paris or America/Los_Angeles. locale string The End-User’s locale, represented as a BCP47 [RFC5646] language tag. This is typically an ISO 639-1 Alpha-2 [ISO639‑1] language code in lowercase and an ISO 3166-1 Alpha-2 [ISO3166‑1] country code in uppercase, separated by a dash. For example, en-US or fr-CA. As a compatibility note, some implementations have used an underscore as the separator rather than a dash, for example, en_US; Implementations MAY choose to accept this locale syntax as well. phone_number string The End-User’s preferred telephone number. E.164 [E.164] is RECOMMENDED as the format of this Claim. For example, 1 (425) 555-1212 or 56 (2) 687 2400. address JSON object The End-User’s preferred address. The value of the address member is a JSON [RFC4627] structure containing some or all of the members defined in Section 2.4.2.1. updated_time string Time the End-User’s information was last updated, represented as a RFC 3339 [RFC3339] datetime. For example, 2011-01-03T23:58:42+0000.

Parameters:

  • attribute

Returns:

  • mixed



541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
# File 'lib/openid_connect_client.rb', line 541

def get(attribute)
    if @user_info.include? attribute
        return @user_info["#{attribute}"]
    end
    
     = get_provider_config_value(:userinfo_endpoint)
    schema = "openid"
     += "?schema=#{schema}"
    headers = {"Authorization" => "Bearer #{@access_token}"}
    user_data = fetch_url(, nil, headers).body_str
    
    if user_data.nil? || user_data.empty?
        raise OpenIDConnectClientException, "Unable to get #{attribute} from the provider."
    end
    
    user_json = JSON[user_data]
    @user_info = user_json
    
    if @user_info.include? attribute
        return @user_info["#{attribute}"]
    end
    
    return nil
end

#provider_urlObject

Returns string.

Returns:

  • string



634
635
636
637
638
639
640
641
# File 'lib/openid_connect_client.rb', line 634

def provider_url()
    # If the provider URL has been set then return it.
    unless self.instance_variable_defined? :@provider_url
        raise OpenIDConnectClientException, "The provider URL has not been set."
    end

    @provider_url
end

#provider_url=(url) ⇒ Object

Returns string.

Parameters:

  • provider_url

Returns:

  • string



648
649
650
651
652
653
654
# File 'lib/openid_connect_client.rb', line 648

def provider_url=(url)
    unless is_valid_url?(url)
        raise OpenIDConnectClientException, "Invalid URL."
    end

    @state[:issuer] = url
end

#redirect_urlObject

Gets the URL of the current page we are on, encodes, and returns it

Returns:

  • string



662
663
664
665
666
667
668
669
# File 'lib/openid_connect_client.rb', line 662

def redirect_url()
    # If the redirect URL has been set then return it.
    unless self.instance_variable_defined? :@redirect_url
        raise OpenIDConnectClientException, "The redirect URL has not been set."
    end

    @redirect_url
end

#redirect_url=(url) ⇒ Object

Returns string.

Parameters:

  • url

    Sets redirect URL for auth flow

Returns:

  • string



676
677
678
679
680
681
682
# File 'lib/openid_connect_client.rb', line 676

def redirect_url=(url)
    unless is_valid_url?(url)
        raise OpenIDConnectClientException, "Invalid URL."
    end

    @redirect_url = url
end

#registerObject

Dynamic registration

Returns:

  • void



572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
# File 'lib/openid_connect_client.rb', line 572

def register()
    registration_endpoint = get_provider_config_value(:registration_endpoint)
    
    send_object = {
        redirect_uris: [@redirect_url],
        client_name: @client_name
    }
    
    @response = fetch_url(registration_endpoint, JSON[send_object])
    json_response = JSON[response]
    
    if not json_response
        raise OpenIDConnectClientException, "Error registering: JSON response received from the server was invalid."
    elsif json_response[:error_description]
        raise OpenIDConnectClientException, json_response[:error_description]
    end
    
    if json_response[:client_id]
        @client_secret = json_response[:client_id]
    else
        raise OpenIDConnectClientException, "Error registering: Please contact the OpenID Connect provider and obtain a Client ID and Secret directly from them."
    end
end

#scopes=(scopes) ⇒ Object

Parameters:

  • scopes
    • example: openid, given_name, etc…



618
619
620
# File 'lib/openid_connect_client.rb', line 618

def scopes=(scopes)         
    @scopes = scopes.split(' ') if scopes
end