Class: Talis::Authentication::Login
- Includes:
- HTTParty
- Defined in:
- lib/talis/authentication/login.rb
Overview
Represents the user login flow for server-side applications. A prerequisite to using this class is having an application registered with Persona in order to obtain an app ID and secret. Application registration also provides Persona a callback URL to POST the login response back to the application.
Instance Attribute Summary collapse
-
#error ⇒ String
readonly
If present, this will be the reason why the login failed.
-
#state ⇒ String
readonly
A non-guessable alphanumeric string used to prevent CSRF attacks.
-
#user ⇒ Talis::User
readonly
The logged-in user.
Instance Method Summary collapse
-
#generate_url(require: nil) ⇒ String
Use this URL to redirect the user wishing to login to their auth provider.
-
#initialize(app_id:, secret:, provider:, redirect_uri:) ⇒ Login
constructor
Creates a new login object to manage the login flow.
-
#logout_url(redirect_url) ⇒ String
Logs a user out by terminating the session with Persona.
-
#redirect_uri ⇒ String
The redirect to follow once login has successfully completed.
-
#valid? ⇒ Boolean
Indicate whether or not the login succeeded.
-
#validate!(payload:, state:) ⇒ Object
Validate a login request after the user has logged in to their auth provider.
Constructor Details
#initialize(app_id:, secret:, provider:, redirect_uri:) ⇒ Login
Creates a new login object to manage the login flow.
61 62 63 64 65 66 67 68 |
# File 'lib/talis/authentication/login.rb', line 61 def initialize(app_id:, secret:, provider:, redirect_uri:) @uuid = UUID.new @app = app_id @secret = secret @provider = provider @redirect_uri = redirect_uri end |
Instance Attribute Details
#error ⇒ String (readonly)
Returns if present, this will be the reason why the login failed.
52 53 54 |
# File 'lib/talis/authentication/login.rb', line 52 def error @error end |
#state ⇒ String (readonly)
Returns a non-guessable alphanumeric string used to prevent CSRF attacks. Store this in the user session after generating a login URL.
46 47 48 |
# File 'lib/talis/authentication/login.rb', line 46 def state @state end |
#user ⇒ Talis::User (readonly)
Returns the logged-in user. This will be nil unless validation has passed.
49 50 51 |
# File 'lib/talis/authentication/login.rb', line 49 def user @user end |
Instance Method Details
#generate_url(require: nil) ⇒ String
Use this URL to redirect the user wishing to login to their auth provider. After generating the URL the state will be available to store in a session.
77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/talis/authentication/login.rb', line 77 def generate_url(require: nil) @state = Digest::MD5.hexdigest("#{@app}::#{@uuid.generate}") params = { app: @app, state: @state, redirectUri: @redirect_uri } params = params.merge(require: 'profile') if require == :profile params = params.to_query "#{self.class.base_uri}/auth/providers/#{@provider}/login?#{params}" end |
#logout_url(redirect_url) ⇒ String
Logs a user out by terminating the session with Persona.
133 134 135 |
# File 'lib/talis/authentication/login.rb', line 133 def logout_url(redirect_url) "#{self.class.base_uri}/auth/logout?redirectUri=#{redirect_url}" end |
#redirect_uri ⇒ String
The redirect to follow once login has successfully completed.
126 127 128 |
# File 'lib/talis/authentication/login.rb', line 126 def redirect_uri @payload.present? ? @payload['redirect'] : @redirect_uri end |
#valid? ⇒ Boolean
Indicate whether or not the login succeeded.
120 121 122 |
# File 'lib/talis/authentication/login.rb', line 120 def valid? @error.nil? end |
#validate!(payload:, state:) ⇒ Object
Validate a login request after the user has logged in to their auth provider. Validation will fail if the provided payload:
-
Is not a hash.
-
When decoded, contains invalid JSON.
-
Has no state or the state it contains does not match the param state.
-
Has an invalid signature.
If validation succeeds, the #user attribute will return the logged-in user. If it fails, check the #error attribute for the reason why.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/talis/authentication/login.rb', line 100 def validate!(payload:, state:) return @error = 'payload is not a hash' unless payload.is_a? Hash key = 'persona:payload' return @error = "payload missing key #{key}" unless payload.key? key @payload = decode_and_parse_payload(payload) return @error = 'payload is not valid JSON' if @payload.nil? state_error = 'payload state does not match provided' return @error = state_error if @payload['state'] != state signature_error = 'payload signature does not match expected' return @error = signature_error unless signature_valid?(@payload) @user = build_user(@payload) end |