Class: NuID::SDK::API::Auth

Inherits:
Object
  • Object
show all
Includes:
HTTParty
Defined in:
lib/nuid/sdk/api/auth.rb

Overview

This class wraps the NuID Auth API endpoints for simpler integration into existing authentication flows.

Examples:

User Registration

class UsersController < ApplicationController
  NUID_API = ::NuID::SDK::API::Auth.new(ENV["NUID_API_KEY"])

  # The registration form should send the verified credential to be
  # recorded in the NuID Auth API. The response to that interaction
  # will provide a `nu/id` key in the response which should be stored
  # with the newly created user record.
  #
  # The "verified credential" is generated by your client application
  # using `Zk.verifiableFromSecret(password)` from the `@nuid/zk` npm
  # package.
  def register
    credential_res = nuid_api.credential_create(params[:credential])
    unless credential_res.code == 201
      return render_error("Unable to create the credential", :bad_request)
    end

    user = User.create!({
      email: params[:email].strip.downcase,
      first_name: params[:firstName],
      last_name: params[:lastName],
      nuid: credential_res.parsed_response["nu/id"]
    })

    render(json: { user: user }, status: :created)
  rescue => exception
    render_error(exception.message, 500)
  end
end

User Login

class SessionsController < ApplicationController
  NUID_API = ::NuID::SDK::API::Auth.new(ENV["NUID_API_KEY"])

  # Get a challenge from the Auth API. The client form should request
  # a challenge as the first of two phases to login. Once a succesful
  # challenge has been fetched, return it to the client so a proof
  # can be generated from the challenge claims and the user's password.
  def 
    user = User.where(email: params[:email].strip.downcase).first
    return render_error("User not found", :unauthorized) unless user

    credential_res = nuid_api.credential_get(user.nuid)
    unless credential_res.code == 200
      return render_error("Credential not found", :unauthorized)
    end

    credential = credential_res.parsed_response["nuid/credential"]
    challenge_res = nuid_api.challenge_get(credential)
    unless challenge_res.code == 201
      return render_error("Cannot create a challenge", 500)
    end

    challenge_jwt = challenge_res.parsed_response["nuid.credential.challenge/jwt"]
    render(json: { challengeJwt: challenge_jwt }, status: :ok)
  rescue => exception
    render_error(exception.message, 500)
  end

  # Verify is the second part of the login process. The params
  # provided here include the user identification param (email or
  # username), the unaltered challenge_jwt retrieved in phase 1 of login
  # (see #login_challenge above), and the proof that was generated from
  # the challenge_jwt claims and the user secret.
  #
  # The "proof" is generated by your client application using
  # `Zk.proofFromSecretAndChallenge(password, challenge_jwt)` from the
  # `@nuid/zk` npm package.
  def 
    user = User.where(email: params[:email].strip.downcase).first
    return render_error("User not found", :unauthorized) unless user

    challenge_res = nuid_api.challenge_verify(params[:challengeJwt], params[:proof])
    unless challenge_res.code == 200
      return render_error("Verification failed", :unauthorized)
    end

    render(json: { user: user }, status: :ok)
  rescue => exception
    render_error(exception.message, 500)
  end
end

See Also:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key) ⇒ Auth

Create an HTTParty instance for dispatching HTTP requests.

All endpoints return the HTTParty Response object, with ‘HTTParty::Response#parsed_response` containing the JSON body converted to a hash.

Parameters:

  • api_key (string)

    The Auth API Key

See Also:



108
109
110
111
112
113
114
# File 'lib/nuid/sdk/api/auth.rb', line 108

def initialize(api_key)
  @api_key = api_key
  self.class.headers({
    "X-API-Key" => @api_key,
    "Accept"    => "application/json"
  })
end

Instance Attribute Details

#api_keyObject (readonly)

Returns the value of attribute api_key.



98
99
100
# File 'lib/nuid/sdk/api/auth.rb', line 98

def api_key
  @api_key
end

Instance Method Details

#challenge_get(credential) ⇒ HTTParty::Response

Get a credential ‘challenge` from the API, usually during login flow. The returned `challenge` can be used to generate a proof from the user’s secret. Used in conjunction with #challenge_verify.

Parameters:

  • credential (Hash)

    A ‘credential` is usually returned by the #credential_get method

Returns:

See Also:



128
129
130
# File 'lib/nuid/sdk/api/auth.rb', line 128

def challenge_get(credential)
  _post("/challenge", {"nuid/credential" => credential})
end

#challenge_verify(challenge_jwt, proof) ⇒ HTTParty::Response

Verify a credential challenge with a proof generated from the challenge claims and the user’s secret. Generated proof from the claims contained in the ‘challenge_jwt` and the user’s secret. This proof is generated by ‘Zk.proofFromSecretAndChallenge(secret, challenge)` available in the npm package `@nuid/zk`.

Parameters:

  • challenge_jwt (String)

    the ‘nuid.credential.challenge/jwt` returned by #challenge_get

  • proof (Hash)

    the generated proof from the challenge jwt claims and user secret

Returns:

See Also:



147
148
149
150
151
152
# File 'lib/nuid/sdk/api/auth.rb', line 147

def challenge_verify(challenge_jwt, proof)
  _post("/challenge/verify", {
    "nuid.credential.challenge/jwt" => challenge_jwt,
    "nuid.credential/proof"         => proof
  })
end

#credential_create(verified_credential) ⇒ HTTParty::Response

Create a credential from a verified credential (meaning a credential generated from the user’s secret). Usually used during user registration. The parsed response body contains the new credential and the user’s unique “nu/id” which should be used as a reference to the user’s credential for later authentication attempts.

Parameters:

  • verified_credential (Hash)

    The hash returned by calling ‘Zk.verifiableFromSecret(secret)`

Returns:

  • (HTTParty::Response)

    use ‘Response#parsed_response` to get the parsed JSON body

See Also:



167
168
169
# File 'lib/nuid/sdk/api/auth.rb', line 167

def credential_create(verified_credential)
  _post("/credential", {"nuid.credential/verified" => verified_credential})
end

#credential_get(nuid) ⇒ HTTParty::Response

Fetch a credential by it’s unique ‘nuid`. The `nu/id` paramter is extracted from the `#parsed_response` of #credential_create.

Generally you will end up storing the nuid with your user record during registration. Later during login use the nuid to fetch the credential using this method, and pass the Response#parsed_response directly to #challenge_get.

Parameters:

  • nuid (String)

    unique key for the credential

Returns:

  • (HTTParty::Response)

    use ‘Response#parsed_response` to get the parsed JSON body



182
183
184
# File 'lib/nuid/sdk/api/auth.rb', line 182

def credential_get(nuid)
  self.class.get("/credential/#{nuid}")
end