Skip to content

Authorization

Stephen Hurwit edited this page Aug 24, 2022 · 6 revisions

Authorization

The Core BB enables authorization by providing authenticated entities with tokens that can be validated by other services in the Rokwire ecosystem. These tokens are JSON Web Tokens (JWTs) that encode the relevant information about the entity needed to determine what resources they should be able to access.

The public key of the keypair used to sign these tokens is published publicly by the Core BB so that any relying service may easily access this key and use it to validate a token that it received.

Token Types

There are several types of tokens that are provided by the Core BB.

  • Access: Access tokens are JWTs populated with information necessary to authorize access to resources throughout the system.
    • User: A User Access Token can be generated through the user Sign In Flow and Refresh Flow. These tokens provide full access to a user's data and therefore MUST ONLY be sent to other first-party Rokwire Building Blocks/services.
    • Anonymous: An Anonymous Access Token can be generated through the Anonymous Flow. These tokens can be generated without any authentication, and therefore MUST ONLY be allowed to access public data that any user of the application would be permitted to access.
    • Scoped: A Scoped Access Token may be generated to grant limited authorization to a specific third-party service through the user Scoped Flow. These tokens MUST ONLY be sent to the specified Third-Party Service and other first-party Building Blocks/services.
    • Service: Service Access Tokens can be generated through the Service Flow to allow services to authorize each other.
  • Refresh: Refresh tokens are opaque tokens that can be generated along with a Login Session to enable applications to retrieve fresh access tokens without user interaction. Upon use, these tokens will be rotated and the new refresh token will be returned. These tokens MUST ONLY be sent to the Core BB.
  • CSRF: CSRF tokens are JWTs populated with the minimum information necessary to verify a match with the Access Token when accessing resources through a web application where CSRF prevention is a concern.

Token Contents

The standard token claims that will be available are as follows:

type Claims struct {
	// Required Standard Claims: sub, aud, exp, iat
	jwt.StandardClaims
	OrgID         string `json:"org_id" validate:"required"`   
	AppID         string `json:"app_id"`                       
	SessionID     string `json:"session_id"`                   
	Purpose       string `json:"purpose" validate:"required"`  
	AuthType      string `json:"auth_type" validate:"required"`
	Permissions   string `json:"permissions"`  
	Scope         string `json:"scope"`        
	Anonymous     bool   `json:"anonymous"`    
	Authenticated bool   `json:"authenticated"`
	Service       bool   `json:"service"`    
	FirstParty    bool   `json:"first_party"`
	Admin         bool   `json:"admin"` 
	System        bool   `json:"system"`

	Name        string            `json:"name,omitempty"`
	Email       string            `json:"email,omitempty"`
	Phone       string            `json:"phone,omitempty"`

	ExternalIDs map[string]string `json:"external_ids,omitempty"`

	UID string `json:"uid,omitempty"`
}

Standard Claims

The following standard JWT claims are used and guaranteed to be populated.

Name Key Type Description
Subject sub string The unique identifier of the entity the token was issued for. This must be used as the entity's primary ID. This will be populated with the entity's Account ID.
Audience aud string (comma-separated) An identifier for the intended recipient of the token. The "rokwire" audience is reserved and indicates that the token should be accepted by all first-party Rokwire services, such as Building Blocks. Otherwise, a specific Service ID may be provided. The audience will be encoded as a comma-separated string in the case that the token is intended for use by multiple services.
Expiration Time exp DateTime The time after which the token is expired and no longer valid. This claim will be a datetime string encoded in the RFC 3339 format.
Issued At iat DateTime The time at which the token was issued. This claim can be used to calculate the age of the token. It will be a datetime string encoded in the RFC 3339 format.

Custom Claims

The following additional custom claims are available in the token. The "Required" field indicates whether or not the claim will always be specified in Access Tokens.

Name Key Type Required Description
Organization ID org_id string false The ID of the Organization that the entity's account belongs to. This is the primary identifier used for multi-tenancy throughout the system. When storing or retrieving user data, this ID must be associated to maintain appropriate data isolation between system tenants. This claim may be empty for Service Accounts if the account spans across all organizations.
Application ID app_id string false The ID of the Application that the entity's account belongs to. This claim may be empty for Service Accounts if the account spans across all applications.
Session ID session_id string false The ID of the Login Session that was used to generate this token. This claim may be empty if the token is not associated with a login session.
Purpose purpose string true The purpose of the token. This may either be "access" for Access Tokens or "csrf" for CSRF tokens.
Auth Type auth_type string true The Authentication Type used to generate this token/login session.
Permissions permissions string (comma-separated) false A comma-separated string that lists the Permissions granted to this entity within the specified application and organization. This claim may be empty if no permissions are granted.
Scope scope string (comma-separated) false A comma-separated string that lists the Scopes that this token can be used to access. This claim may be empty if no scopes are granted.
Anonymous anonymous boolean true A flag indicating that the token was generated for an Anonymous User. In this case, the "sub" claim will contain the user's Anonymous ID
Authenticated authenticated boolean true A flag indicating that this token was generated in response to an authentication request, as opposed to a refresh request.
Service service boolean true A flag indicating that this token was generated for a Service Account.
First-Party first_party boolean true A flag indicating that this token was generated for use by first-party services. If the "service" flag is set, this indicates that the service is a first-party service (eg. Building Block). Otherwise, this indicates that the token is a Scoped Token for use by a third-party service.
Admin admin boolean true A flag indicating that this token was generated for an Admin user.
System system boolean true A flag indicating that this token was generated for a System Admin.
External IDs external_ids map (string : string) false An object containing user's External IDs. These IDs should only be used for the purpose of communicating with external systems. Internally the "sub" claim should be used to identify the user instead.
UID uid string false The user identifier associated with the specified Auth Type. For example, if the Auth Type is email, this will be the user's email address.

Personal Information Claims

Claims containing personal info on the user for display purposes. These claims MUST NOT be used as an identifier for the user or shared with any third-party entities.

Name Key Type Required Description
Name name string false The user's preferred display name.
Email email string false The user's primary email address.
Phone phone string false The user's primary phone number.

Token Verification

Tokens may be verified by using the Service Registration record for the auth service. This service registration record is publicly available through the /bbs/service-regs endpoint.

User Authorization

Users may authorize services to perform certain actions or access certain data on their behalf. To do this, the user may generate a Scoped Token through the Scoped Flow.

Scopes

Scopes are the fundamental unit used to define what actions and resources an entity is authorized to access on behalf of a user. Scopes are structured in the following format {service_id}:{resource}:{operation} where:

  • service_id - The Service ID of the service that the scope applies to. Eg. the core Service ID indicates that this scope applies for the Core BB.
  • resource - The resource that is covered by the scope. Eg. the email resource may indicate that this scope applies to the user's email address.
  • operation - The operation that is permitted on the specified resource. Eg. the read operation may indicate that the scope authorizes read access.

Scopes are granted by a user to a service for to enable the service to provide them with some functionality in exchange for limited access to their data in the Rokwire ecosystem. They can do this through the Scoped Flow

Note: While Permissions are used to define which administrative actions can be taken, scopes indicate what actions may be taken on a user's behalf.

Admin Authorization

Admin authorization is managed through the permission, group, and role concepts. Admin accounts may be assigned any combination of these elements to allow for flexible and easy management of privileges across the system.

Permissions

The base unit of admin authorization in the Rokwire ecosystem is the permission. Permissions are defined and used by Rokwire services to authorize administrative actions.

Permissions must be:

  • Unique - Permissions should be globally unique throughout the system. Each permission must be associated with a single implementing service. Two services cannot define a permission with the same name.
  • Static - The meaning of a permission should remain unchanged once it is defined. Removing access to resources or operations from a permission is likely to break existing workflows. Adding new resources or operations to a permission can result in users gaining more access than originally intended.
  • Global - Permissions exist outside of the multi-tenancy model and are globally defined across all organizations and applications. This is because permissions are defined by the services and must be consistent throughout the system.
  • Grantable - Each permission contains a list of approved assigners. Only admins with one of these assigner permissions will be allowed to grant the permission.

Aside from the requirements listed above, the exact definition of a permission is up to the implementing service, however the following guidelines are recommended:

Permissions should be:

  • Specific - Since permissions are the fundamental authorization unit, they should be defined for a very specific purpose. It is easy to manage multiple permissions once they are defined using roles and groups, but it will require code changes to split up a permission that was defined too broadly. Usually this will mean that each permission should be associated with a particular:
    • Resource - Permissions should not be shared between endpoints that handle different components of the system. For example, the /admin/roles endpoint should have a separate permission from the /admin/groups endpoint.
    • Operation - Separate permissions should be defined for read, write, and delete operations. For example, the PUT and POST operations for each endpoint should have a separate permission from the GET operation and the DELETE operation. A separate all_ permission can be created to allow all operations to be performed (in addition to the separate get_, update_, delete_ permissions) if all of the operations are commonly assigned together.
  • Descriptive - Permission names should clearly and concisely describe the actions that they allow the user to take. For example, the permission to grant read access to the "roles" resource should be named get_roles.

Using the guidelines described above, the following permissions should be defined for the /admin/roles and /admin/groups endpoints should use the following permissions:

  • get_roles - GET /admin/roles

  • update_roles - PUT, POST /admin/roles

  • delete_roles- DELETE /admin/roles

  • all_roles- GET, PUT, POST, DELETE /admin/roles

  • get_groups - GET /admin/groups

  • update_groups - PUT, POST /admin/groups

  • delete_groups - DELETE /admin/groups

  • all_groups- GET, PUT, POST, DELETE /admin/groups

Roles

A role is a collection of permissions that can be created to easily assign and manage user access. It can be defined and managed per application, organization pair to enable certain users to perform a specific administrative job within that App/Org. Each role must be given a name and description that clearly conveys its intended purpose and use. Roles may be managed at the system level to prevent organization admins from modifying them.

Groups

A group is a collection of users that share the same roles and permissions. It can be defined and managed per application, organization pair to allow admins to easily view and manage users with similar responsibilities and privileges. Each group must be given a name that clearly conveys its intended purpose and use. Groups may be managed at the system level to prevent organization admins from modifying them.

Auth Flows

There are several different process flows that must be followed to authenticate and authorize entities in the system.

Sign In Flow

The most basic auth flow in the system is the Sign In Flow. This is the flow that users will take when establishing a new Login Session. To do so, the user must authenticate using an Auth Type that has previously been associated with their account through the /services/auth/login endpoint. The response of a successful authentication will contain the user's Account information, an Access Token, and a Refresh Token if enabled.

Note: For admin users, the /admin/auth/login endpoint should be used instead

The Sign In Flow may complete unsuccessfully in several situations. If the provided credentials do not match with an existing account, the user must Sign Up before they can login. If the user has not yet Verified the auth type they attempted to use, they must do so before continuing. If the provided credentials are not valid, an authentication error will be returned.

Sign Up Flow

When a new user would like to create an Account for the first time, they must perform the Sign Up Flow. This will generate a new account record in the system and initiate Verification if necessary. This flow is also initiated through the /services/auth/login endpoint, however some additional parameters may be required when compared to the Sign In Flow depending on the Auth Type.

Note: For admin users, the /admin/auth/login endpoint should be used instead

Upon completing the sign up request, the user must perform any necessary verification, then they will be able to follow the Sign In Flow to login to the account and receive their access token.

If the provided credentials already match with an existing account, an error will be returned.

Refresh Flow

The Refresh Flow allows a client application to retrieve a new Access Token once the current access token expires without any user interaction. This flow may be disabled for some Application Types. If it is enabled, the client will receive a Refresh Token along with the access token. To initiate the refresh flow, this refresh token is sent to the /services/auth/refresh endpoint.

Note: For admin users, the /admin/auth/refresh endpoint should be used instead

Anonymous Flow

For applications that do not require user authentication to access some features, the Anonymous Flow can be supported. This flow allows users to receive an Anonymous Access Token without creating an account or providing any personal information. For this flow a request can be made to the /services/auth/login endpoint using the "anonymous" Auth Type.

This request will return an Anonymous ID that can be stored in the client. When making future requests to login, this ID can be provided to maintain consistency.

Warning: Since an API Key is the only form of credential needed to perform this flow, an anonymous token should ONLY be used to access public information. No private user information should be stored associated with an Anonymous ID. An Anonymous Token should NEVER receive access to any private user data.

Scoped Flow

The Scoped Flow is intended for users to authorize Third-Party Services to access their data. In order to use this flow, the Sign In Flow must be performed first to retrieve a User Access Token. This token can then be sent to the /services/auth/authorize-service endpoint to authorize a specific service with specific Scopes and receive a Scoped Access Token that can be shared with that service.

Upon receiving the Scoped Access Token, the service can then verify the token, then pass it along to other Rokwire Building Blocks to retrieve information about the user that has been approved.

Service Flow

To authorize requests between Services, the Service Flow can be used to generate a Service Access Token for a Service Account. The Service Flow involves performing one of the supported forms of Service Account Authentication by making a request to the /bbs/access-token endpoint.

Note: For third-party services, the /tps/access-token endpoint should be used instead

In general, the service flow should only be used when the operation being performed is not associated with a specific user request. For example, periodic tasks that retrieve or operate on data owned by a different service would need to make use of this flow. If a user sends a request to one Building Block, and in the process of serving this request, another Building Block must be contacted, the user's token should be passed instead to ensure that the request to the secondary BB is associated with that user appropriately.

Exceptions to this guideline occur when the Building Blocks are performing some form of administrative action that the user themself would not be authorized to perform, or some additional data that the user does not have access to must be used to perform the request. In both cases, care must be taken to avoid exposing any of this additional data or access to administration functions to the user directly.

Login Sessions

Whenever a user successfully authenticates through the Sign In Flow, a new login session will be created. This will store information about the user account, the device they authenticated from, the authentication method used, and other state information. These login sessions are used to enable the Refresh Flow and keep track of the necessary to detect and prevent abuse of Refresh Tokens.

There are several mechanisms available to manage the lifetime of login sessions in the Login Session Settings of an Application/Organization. These include the following:

  • Max Concurrent Sessions - The maximum number of concurrent login sessions that a single user can have. Once this maximum has been reached, the session that has not been used in the longest time will be removed before any new ones are created.
  • Inactivity Expiration Policy - A policy that defines the maximum duration that a login session can be valid without being used. Using a the Refresh Flow with a token from this session will reset this timer.
  • Time Since Login Expiration Policy - A policy that defines the maximum duration that a login session can be valid since it was created by a login event. If this policy is active, no session can be older than the specified duration.
  • Yearly Expiration Policy - A policy that defines a specific day/time during the year that all login sessions become invalid. Each year on the specified day/time, any login session that was created over a year ago will be removed.