Profile Mapping

Auto association of group memberships based on Okta/HRIS metadata.

Architecture Profile Mapping

Okta Auth Provider

Access Manager uses Okta single sign-on for authenticating users. At GitLab, an Okta application has been configured for Access Manager and has been associated with the GitLab AllStaff group which provide access to all team members to access Access Manager as a normal user.

At GitLab, We have mapped Okta user data inherited from BambooHR and/or Workday (migration in progress). More information is available in enterprise-apps/intake#300 - Workday: Okta Analysis.

All administrator and approver permissions are managed within Access Manager using explicitly granted Auth Roles.

You can learn more about how the Laravel framework uses Socialite and the Okta Socialite Provider for authenticating Okta users.

Auth Provider Groups

An AuthProviderGroup allows user metadata to be used to automatically create an AuthGroupUser record, effectively authorizing that AuthUser to have inherited access to any ApprovalPolicy, AuthRole, or SaaSProviderRole that the AuthGroup has been granted.

At GitLab, this is used for automatically associating an AuthUser with the AuthGroup for their respective entity, country, division, department, department group (team), job family, and job specialty. Additional AuthGroup(s) can be granted within Access Manager.

If a user changes departments and/or roles (ex. job family or job specialty), they will automatically be associated with the new AuthGroup(s) based on their updated Okta metadata the next time they sign in.

The workflow process for removing user from a group is undergoing business requirements and considerations review, however the preliminary design is that the AuthGroupUser record will have the expires_at value set for the last day of their role.

Default Groups

If an AuthProviderGroup type is set to default, any user that signs in with that AuthProvider will be granted access to the AuthGroup specified in auth_group_id automatically without any conditions. These are useful for baseline entitlements for all users.

Auth User Meta Data

In the example below, the Okta user metadata contains the key gl_department and the value Development.

1{
2 "id": "0c621173-6062-46c1-a3b7-f9434b14e3e0",
3 "short_id": "0c621173",
4 "auth_provider_id": "591916f1-c16e-4637-9a34-cb4b418816eb",
5 "full_name": "Milo Hoffman",
6 "email": "mhoffman@gitlab.com",
7 "provider_meta_data": {
8 "sub": "a1b2c3d4e5f7g7h8i9j0",
9 "updated_at": 1623315787,
10 "gl_entity": "Inc",
11 "locale": "US",
12 "gl_job_title": "Backend Engineer, Ecosystem",
13 "gl_division": "Engineering",
14 "gl_department": "Development",
15 "gl_manager_name": "Winston, Gary",
16 "gl_manager_id": "67890",
17 "gl_employee_id": "12345",
18 "gl_user_id": "1234567",
19 "gl_slack_id": "ABCDEFGHI",
20 "gl_username": "mhoffman-gl",
21 "preferred_username":"mhoffman@gitlab.com"
22 },
23 "provider_token": "(encrypted)",
24 "count_current_failed_logins": "0",
25 "last_successful_login_at": "2021-08-05 14:32:26",
26 "last_failed_login_at": null,
27 "last_activity_at": "2021-08-05 17:58:31",
28 "expires_at": null,
29 "locked_at": null,
30 "created_at": "2021-08-02 07:32:01",
31 "updated_at": "2021-08-02 07:32:01",
32 "state": "active"
33}

Auth Provider Groups

In the example below, an AuthProviderGroup has been previously created with the type value of meta, which specifies that Access Manager should look for the gl_department key and Development value in the user's metadata. If the user metadata contains a match, the user will be added to the AuthGroup with ID b47cc8c7-cdef-4886-9b18-635540e14dc9.

1{
2 "id": "6458937f-2183-4e69-839a-d525f516913d",
3 "short_id": "6458937f",
4 "auth_tenant_id": "be3e9f47-453f-4fa3-8890-60fa360fb8d9",
5 "auth_provider_id": "591916f1-c16e-4637-9a34-cb4b418816eb",
6 "auth_group_id": "b47cc8c7-cdef-4886-9b18-635540e14dc9",
7 "type": "meta",
8 "meta_key": "gl_department",
9 "meta_value": "Development",
10 "created_at": "2020-11-17 01:49:32",
11 "updated_at": "2020-11-17 01:49:32",
12 "state": "active"
13}

Access Manager will loop through all AuthProviderGroups when a user authenticates and check if the AuthProvider sign on response metadata includes any key that matches the value in the user's metadata. If there is a match, the user will automatically be attached to the AuthGroup specified in auth_group_id.

Authentication and Authorization Logic

1// App\Http\Controllers\Auth\Okta\LoginController::handleCallback()
2 
3// Get auth provider fields to map OKTA metadata to user account fields
4$auth_provider_groups = Models\Auth\AuthProviderGroup::query()
5 ->where('auth_tenant_id', $this->okta_provider->auth_tenant_id)
6 ->where('auth_provider_id', $this->okta_provider->id)
7 ->where('type', 'meta')
8 ->get();
9 
10// Loop through authentication provider groups
11foreach($auth_provider_groups as $provider_group) {
12 
13 // Define variables for use in conditional statements below
14 $meta_key = $provider_group->meta_key;
15 $meta_value = $provider_group->meta_value;
16 
17 // Check if provider key exists in OKTA metadata
18 if($okta_meta_data->has($meta_key)) {
19 
20 // Check if the values match
21 if($okta_meta_data[$meta_key] == $meta_value) {
22 
23 // Check if user has already been associated with group
24 $existing_group = Models\Auth\AuthGroupUser::query()
25 ->where('auth_group_id', $provider_group->auth_group_id)
26 ->where('auth_user_id', $auth_user->id)
27 ->first();
28 
29 // If user has not been associated with group
30 if(!$existing_group) {
31 
32 // Create new group relationship for user
33 $authGroupUserService->store([
34 'auth_tenant_id' => $auth_user->auth_tenant_id,
35 'auth_group_id' => $provider_group->auth_group_id,
36 'auth_user_id' => $auth_user->id,
37 ]);
38 
39 Log::channel('access-manager-auth')->info(
40 'Granted access to group using provider metadata mapping.',
41 [
42 'log_event_type' => 'auth-provider-group-meta-user-created',
43 'log_class' => get_class(),
44 'ip_address' => config('access-manager.log.ip_address.enabled') ? $request->ip() : null,
45 'user_agent' => config('access-manager.log.user_agent.enabled') ? $request->userAgent() : null,
46 'auth_tenant_id' => $this->okta_provider->auth_tenant_id,
47 'auth_provider_id' => $this->okta_provider->id,
48 'auth_provider_slug' => $this->okta_provider->slug,
49 'auth_provider_group_id' => $provider_group->id,
50 'auth_user_id' => $auth_user->id,
51 'auth_group_id' => $provider_group->auth_group_id,
52 'auth_group_slug' => $provider_group->authGroup->slug,
53 ]
54 );
55 
56 } // if(!$existing_group)
57 } // if($okta_meta_data[$meta_key] == $meta_value)
58 } // if($okta_meta_data->has($meta_key))
59} // foreach($auth_provider_groups)

Auth Group Users

This user contains a meta data key and value match, so a new AuthGroupUser record was created.

1 {
2 "id": "20129d53-90af-4c24-b0e1-88eac6b4713b",
3 "short_id": "20129d53",
4 "auth_tenant_id": "be3e9f47-453f-4fa3-8890-60fa360fb8d9",
5 "auth_provider_group_id": "6458937f-2183-4e69-839a-d525f516913",
6 "auth_group_id": "b47cc8c7-cdef-4886-9b18-635540e14dc9",
7 "auth_user_id": "0c621173-6062-46c1-a3b7-f9434b14e3e0",
8 "expires_at": null,
9 "flag_is_manager": 0,
10 "created_at": "2021-08-02 07:32:02",
11 "updated_at": "2021-08-02 07:32:02",
12 "deleted_at": null,
13 "state": "active"
14}

Revoking Access

Access to the group an inherited roles and permissions can be revoked by deleting the record, or setting the expires_at datetime value which is handled by scheduled background job automation. The auth_provider_group_id is used for relationship mapping of all AuthGroupUser records that were created by the AuthProviderGroup auto association.