Skip to content

Authorization Mechanism

Conrad Boyd Elliott Gustafson edited this page Oct 18, 2022 · 10 revisions

Purpose

This document details the inputs, behaviour, and outputs of the FAM Runtime Authorization Lookup.

Inputs

The FAM Runtime Authorization Lookup component is a Lambda function that receives an event each time AWS Cognito is required to create a JSON Web Token as part of an OIDC authentication flow.

In order to successfully query the FAM data model, the Lambda must extract three pieces of information from the event.

  1. The user_type in order to identify whether the user belongs to IDIR or BCeID Business. (Source: "request"->"userAttributes"->"custom:idp_name")
  2. The user_guid which is the unique identifier of the user within the domain of the identity provider (IDIR or BCeID Business). (Source: "request"->"userAttributes"->"custom:idp_user_id")
  3. The cognito_client_id which identifies the application on behalf of which Cognito facilitated the authentication event. (Source: "callerContext"->"clientId")

These three attributes should be in every event received by the Lambda.

Example Event

{
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "3u3vm7ehhaj2iqkm851t8fl6gp"
    },
    "region": "ca-central-1",
    "request": {
        "groupConfiguration": {
            "groupsToOverride": [
                "ca-central-1_ixb69p4hq_IDIR"
            ],
            "iamRolesToOverride": [],
            "preferredRole": null
        },
        "userAttributes": {
            "cognito:user_status": "EXTERNAL_PROVIDER",
            "custom:idp_display_name": "Gustafson, Conrad CITZ:IN",
            "custom:idp_name": "idir",
            "custom:idp_user_id": "B5ECDB094DFB4149A6A8445A01A96BF0",
            "custom:idp_username": "COGUSTAF",
            "email": "[email protected]",
            "email_verified": "false",
            "family_name": "Gustafson",
            "given_name": "Conrad",
            "identities": "[{\"userId\":\"b5ecdb094dfb4149a6a8445a01a96bf0@idir\",\"providerName\":\"IDIR\",\"providerType\":\"OIDC\",\"issuer\":null,\"primary\":true,\"dateCreated\":1664399277929}]",
            "name": "Conrad Gustafson",
            "preferred_username": "b5ecdb094dfb4149a6a8445a01a96bf0@idir",
            "sub": "f7e49325-3796-4663-8745-4161745e358c"
        }
    },
    "response": {
        "claimsOverrideDetails": null
    },
    "triggerSource": "TokenGeneration_HostedAuth",
    "userName": "idir_b5ecdb094dfb4149a6a8445a01a96bf0@idir",
    "userPoolId": "ca-central-1_ixb69p4hq",
    "version": "1"
}

Role Lookup Behaviour

The primary behaviour of the Lambda function is to query the FAM database to find out the list of user role assignments the client application needs to be aware of. For MVP, only directly assigned roles are taken into account (future versions will support role groups as well). User role assignments that do not apply to the current application are filtered out.

Query

User Identification

SELECT user_id FROM app_fam.fam_user 
     WHERE user_type = {custom:idp_name}
     AND user_guid = {custom:idp_user_id};

Application Identification

SELECT application.application_id FROM app_fam.fam_application application
     JOIN app_fam.fam_application_client client
     ON application.application_id = client.application_id
     WHERE client.cognito_client_id = {clientId};

Finding Applicable User Roles

The following query will find all the roles that apply to the given user within the context of the current application.

SELECT role.role_name, role.client_number_id, parent_role.role_name FROM app_fam.fam_role role
        LEFT JOIN app_fam.fam_role parent_role ON role.parent_role_id = parent_role.role_id
	JOIN app_fam.fam_application application ON role.application_id = application.application_id
	JOIN app_fam.fam_application_client client ON application.application_id = client.application_id
	JOIN app_fam.fam_user_role_xref role_assignment ON role.role_id = role_assignment.role_id
	JOIN app_fam.fam_user user_assigned ON role_assignment.user_id = user_assigned.user_id
	WHERE user_assigned.user_guid = {custom:idp_user_id}
	AND user_assigned.user_type = {custom:idp_name}
	AND client.cognito_client_id = {clientId};

Insert User Behaviour

Ideally, users would be input into the FAM database with their user_guid as their identifier. For version 1.0, FAM does not include the lookup function to find the user_guid by searching for the user with the IDIM web service. The FAM customers will input a new user, if necessary, using the "user name" and "user_type" (for example: "COGUSTAF", "idir").

When the user subsequently logs in through Cognito, the Authorization service will populate the "user_guid" and "cognito_user_id" fields.

User Insert or Update Query

INSERT INTO app_fam.fam_user (user_type, user_guid, cognito_user_id, user_name)
     VALUES( {custom:idp_name}, {custom:idp_user_id}, {sub}, {custom:idp_username})
     ON CONFLICT ON CONSTRAINT fam_usr_uk
     DO
          UPDATE SET user_guid = {custom:idp_user_id},  cognito_user_id = {sub};

Outputs

The output from the function is a simple list of roles that apply to the user for the current application context.

For simple roles that do not have a "parent" role, the convention for the role identifier will be: <role_name>. For example, if the logged-in user is assigned to a role called "FOM-MINISTRY", and that role does not relate to a specific forest client or have a parent role, then the Authorization function will translate the role into a Cognito override group called "FOM-MINISTRY" (no change).

For "forest client" roles (roles that require a forest client identifier for further context), the convention for the role identifier will be: <parent role_name>.<forest client ID>

For example, in the scenario:

  • The logged-in user is assigned to a role called "FOM-SUBMITTER456787"
  • Role FOM-SUBMITTER456787 is associated with a forest client with the ID "000478HH"
  • Role FOM-SUBMITTER456787 has a parent role with a name "FOM-SUBMITTER"

In this scenario, the Authorization function will translate the role into a Cognito override group called "FOM-SUBMITTER.000478HH".

Example Response Event

{
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "3u3vm7ehhaj2iqkm851t8fl6gp"
    },
    "region": "ca-central-1",
    "request": {
        "groupConfiguration": {
            "groupsToOverride": [
                "ca-central-1_ixb69p4hq_IDIR"
            ],
            "iamRolesToOverride": [],
            "preferredRole": null
        },
        "userAttributes": {
            "cognito:user_status": "EXTERNAL_PROVIDER",
            "custom:idp_display_name": "Gustafson, Conrad CITZ:IN",
            "custom:idp_name": "idir",
            "custom:idp_user_id": "B5ECDB094DFB4149A6A8445A01A96BF0",
            "custom:idp_username": "COGUSTAF",
            "email": "[email protected]",
            "email_verified": "false",
            "family_name": "Gustafson",
            "given_name": "Conrad",
            "identities": "[{\"userId\":\"b5ecdb094dfb4149a6a8445a01a96bf0@idir\",\"providerName\":\"IDIR\",\"providerType\":\"OIDC\",\"issuer\":null,\"primary\":true,\"dateCreated\":1664399277929}]",
            "name": "Conrad Gustafson",
            "preferred_username": "b5ecdb094dfb4149a6a8445a01a96bf0@idir",
            "sub": "f7e49325-3796-4663-8745-4161745e358c"
        }
    },
    "response": {
        "claimsOverrideDetails": {
           "groupOverrideDetails": {
               "groupsToOverride": ["FOM-MINSTRY", "FOM-SUBMITTER.000478HH"],
               "iamRolesToOverride": [],
               "preferredRole": ""
            }
        }  
    },


    "triggerSource": "TokenGeneration_HostedAuth",
    "userName": "idir_b5ecdb094dfb4149a6a8445a01a96bf0@idir",
    "userPoolId": "ca-central-1_ixb69p4hq",
    "version": "1"
}
Clone this wiki locally