Aha Builder Core Client

Ruby client for Aha! Builder core authentication services which provides login and signup using email/password, social logins (Google, Github, Microsoft), SAML SSO and password reset.

Installation

Add to your Gemfile:

gem "aha_builder_core", path: "engines/builder_core/client"

Configuration

No configuration is necessary and no environment variables are necessary.

Authentication Flow

The authentication UI is provided completely by the core system. During authentication the user is redirected to the login page, and will return (via HTTP redirect) to the /callback URL when authentication is complete. Your application must implement a callback action at /callback to receive the code. Any value passed in as state is returned verbatim to the callback.

Protection against CSRF atacks is handled internally by the Aha::Auth library and there is no need to use a nonce in the state parameter.

Generate Login URL

Redirect users to the authentication and signup UI:

url = Aha::Auth.(
  state: { return_to: "/" }.to_json,
)
redirect_to url

Redirecting to the login_url must be done with a full page load. It will not work using XHR.

Exchange Authorization Code

In the /callback action callback, you must exchange the code for a session token and refresh token:

result = Aha::Auth.authenticate_with_code(code: params[:code])
# => {
#   session_token: "...",
#   refresh_token: "...",
#   expires_at: Time,
#   user: {
#     id: "user-uuid",
#     first_name: "Jane",
#     last_name: "Doe",
#     email: "[email protected]",
#     email_verified: true
#   }
# }

User Object

The user object returned contains the authenticated user's profile information from the Builder Core system:

  • id: The unique identifier for the user in Builder Core
  • first_name: User's first name. first_name is optional and may not be present.
  • last_name: User's last name. last_name is optional and may not be present.
  • email: User's email address
  • email_verified: Boolean indicating if the email has been verified

Linking to Local User Records

You can use the returned user object to create or update local user records in your application:

# In your callback action
result = Aha::Auth.authenticate_with_code(code: params[:code])

# Find or create a local user record linked to Builder Core user
local_user = User.find_or_initialize_by(auth_identifier: result[:user]["id"])

# Update local user attributes
local_user.update!(
  email: result[:user][:email],
  first_name: result[:user][:first_name],
  last_name: result[:user][:last_name],
  email_verified: result[:user][:email_verified]
)

# Store tokens in session or database
session[:session_token] = result[:session_token]
session[:refresh_token] = result[:refresh_token]
session[:user_id] = local_user.id

# Redirect to application
redirect_to root_path

Validate Session

Validate a session token (with automatic refresh):

session = Aha::Auth.validate_session(session_token, refresh_token: refresh_token)

if session.valid?
  user_id = session.user_id
  # If tokens were refreshed, update stored tokens
  if session.refreshed?
    new_session_token = session.new_session_token
    new_refresh_token = session.new_refresh_token
  end
else
  # Redirect to login
end

Logout

Aha::Auth.logout(session_token: session_token)

User Management

Server-to-server operations (requires api_key):

# Create user
user = Aha::Auth.users.create(
  email: "[email protected]",
  first_name: "Jane",
  last_name: "Doe",
  password: "secure_password"
)

# Find user
user = Aha::Auth.users.find(user_id)

# Update user
user = Aha::Auth.users.update(user_id, first_name: "Janet")

# Delete user
Aha::Auth.users.delete(user_id)

# List users
result = Aha::Auth.users.list(page: 1, per_page: 50)
result[:users]  # Array of User objects
result[:total]  # Total count

Session Management

# List active sessions for a user
sessions = Aha::Auth.sessions.list(user_id: user_id)

# Revoke a session
Aha::Auth.sessions.revoke(session_id)

Error Handling

begin
  Aha::Auth.validate_session(token)
rescue Aha::Auth::InvalidTokenError
  # Token is malformed or has invalid signature
rescue Aha::Auth::ExpiredTokenError
  # Token expired and refresh failed
rescue Aha::Auth::RateLimitError => e
  # Rate limited, retry after e.retry_after seconds
rescue Aha::Auth::UnauthorizedError
  # Invalid API key
rescue Aha::Auth::NotFoundError
  # Resource not found
rescue Aha::Auth::NetworkError => e
  # Connection failed, original error in e.original_error
rescue Aha::Auth::ApiError => e
  # Other API error, check e.status and e.body
end