<div class="gfmr-markdown-container"><div class="gfmr-markdown-source" style="display: none;"># Organization Identity Provider Integration
The PDC uses Keycloak as an Identity Provider (IdP) and/or Service Provider.
Organizations such as funders, data providers, and changemakers that have their
own IdP can integrate with PDC using their own IdP for authentication while PDC
Keycloak and PDC handle authorization within PDC.
This guide lists specific steps to integrate specific IdPs with PDC Keycloak.
Integration requires a kind of three-way handshake between an organization admin
and a PDC admin before a user can log into PDC:
1. The organization admin configures a PDC app integration and sends information
to the PDC admin
2. The PDC admin adds an organization integration and sends information to the
organization admin
3. The organization admin finishes the PDC app integration.
Perform the steps during a live meeting between admins when practical.
For organizations without their own IdP, the PDC administrators can either
manage a Keycloak organization on their behalf (for smaller organizations) or
add a separate realm as an "external" IdP (for larger organizations). In the
latter case, the integration should be configured to allow an organization
member to manage user membership in that realm as if it were the organization's
own IdP. With a separate realm, the users will be "unmanaged" in the new realm
and "managed" in the `pdc` realm. As of this writing, these two options are
available in lieu of a future Keycloak release that includes Fine-Grained Admin
Permissions (FGAP) for the Keycloak organizations capability. When FGAP is
available for Keycloak organizations, the organization in the `pdc` realm should
be configured to allow an organization member to administer its organization,
and this should obsolete the first two options above.
## To Test an Integration
After creating an integration (below), test it using the following steps.
0. Make sure that the user is assigned to PDC within the external IdP
1. Visit the API docs
2. Click "Authorize"
3. Click "Authorize" on the "Available authorizations" modal
4. Enter an email address with the organization's domain
5. Verify that the browser is redirected to the correct IdP (outside PDC)
6. Authenticate (log in)
7. Verify that a redirect back (through Keycloak) to the PDC API docs occurs
8. Try an API call
## External Okta Identity Providers
Before integrating, the PDC team needs to name an identifying alias for each
integrated system, for example `foundation-okta-oidc` or `foundation-okta-saml`,
to be used to link PDC Keycloak with the external IdP.
### Okta Configuration using OIDC (preferred over SAML)
Log in to the admin area to Start an OIDC App Integration (these steps follow
https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_oidc.htm
with the insertion of group steps and appendage of access policy steps).
#### Create a PDC Group
1. On the left nav bar, visit "Directory" -> "Groups"
2. Click "Add group"
3. Set "Name" to `PDC`
4. Set "Description" to `Users who may access the Philanthropy Data Commons`
5. Click "Save"
6. Click the newly created "PDC" group
7. Click "Assign people" and add at least one user.
#### Create a PDC Application
1. On the left nav bar, visit "Applications" -> "Applications"
2. Click "Create App Integration"

3. Click "OIDC"
4. Select "Web Application"
5. Click "Next"
6. Add "App Name" of `Philanthropy Data Commons`
7. Leave "Proof of possession" unchecked
8. Set "Grant type" to `Authorization code` only
9. Set "Sign-in redirect URI" to the endpoint provided by the PDC team, similar
to `https://example.org/realms/pdc/broker/foundation-okta-oidc/endpoint`
**Important**: the name following `broker/` here needs to match the agreed
alias mentioned above
10. Clear the "Sign-out redirect URIs" by clicking the X
11. Under "Assignments" select `Limit access to selected groups`
12. Set the "Selected group(s)" to the `PDC` group created earlier
13. Click "Save"
14. Confirm under "Login" that "Login initiated by" is `App Only`
15. Share the "Client ID" from "Client Credentials" with the PDC team
16. Under "Client Credentials" click "Edit"
17. Set "Client authentication" to `Public key / Private key`
18. Check "Require PKCE as additional verification"
19. Under "Public Keys" -> "Configuration", check "Use a URL to fetch keys…"
20. Set the URL to the JWKS URL of the PDC Keycloak server, provided by the PDC
team, similar to
`https://example.org/realms/pdc/protocol/openid-connect/certs`
21. Click "Save"
22. Click "Save" at an "Existing client secrets will no longer be used" warning.
#### Create an Access Policy and Rule for the Authorization Server
1. On the left nav bar, visit "Security" -> "API" (way down there)
2. Click the desired Authorization Server name, usually "default"
3. Copy the "Metadata URI" value and send it to the PDC team
4. Click the "Access Policies" tab
5. Click "Add New Access Policy"
6. Set "Name" to `PDC`
7. Set "Description" to `Allow users to authenticate to PDC`
8. Set "Assign to" to `The following clients:`
9. Type `P` in the input box and then pick the "PDC" client created above
10. Click "Create Policy"
11. Under the new PDC policy, click "Add rule"
12. Set the "Rule Name" to `Issue tokens to users authenticating to PDC`
13. Reduce the token lifetimes such as to `5 minutes` (access) and `90 minutes`
14. Click "Create rule".
### Okta Configuration using SAML 2.0
#### Save the current PDC keys in a PEM file
1. Visit the PDC Keycloak SAML configuration URL, similar to
`https://example.org/realms/pdc/protocol/saml/descriptor`
2. Within the XML document presented, copy and paste each PEM-encoded value
under "<md:KeyDescriptor use='signing'>…<ds:X509Certificate>", similar to
`MIIC…=`, into a single (new) text file.
3. Surround each of the values from above with PEM headers and footers, namely
`—–BEGIN CERTIFICATE—–` and `—–END CERTIFICATE—–`, each on their
own lines.
4. Line-wrap each of the values from above at 64 characters, according to
https://www.rfc-editor.org/rfc/rfc7468.html#page-5
5. Save the new file with a `.crt` extension, such as `pdc_signing_keys.crt`.
This file will be used below to configure signature validation. When using SAML
with Okta, there is no option to dynamically fetch these keys. So when PDC keys
are updated, the integration will not work until re-uploading the PDC keys. Thus
[OIDC is preferred](#Okta Configuration using OIDC (preferred over SAML)) when
using Okta.
#### Configure Okta App Integration
1. Log in to the admin area to Start a SAML App Integration (these steps follow
https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_saml.htm
)
2. On the left nav bar, visit "Applications" -> "Applications"
3. Click "Create App Integration"

4. Click "SAML 2.0"

5. Click "Next"
6. Set "App Name" to `Philanthropy Data Commons`
7. If you wish to add a logo, one may be found on the [PDC website](https://philanthropydatacommons.org/)
8. Check "Do not display application icon to users" under "App visibility" to
avoid erroneous IdP-initiated login attempts (because users begin the login
flow from PDC Apps and not from the Okta IdP)
9. Click "Next"
10. Paste the Single sign-on URL endpoint provided by the PDC team, similar to
`https://example.org/realms/pdc/broker/foundation-okta-saml/endpoint`
into Okta's "Single sign-on URL"
11. Paste the "SP Entity ID URL" provided by the PDC team, similar to
`https://example.org/realms/pdc` into Okta's "Audience URI (SP Entity ID)"
field
12. Set the "Name ID format" to `EmailAddress`
13. Set the "Application username" to `Email`
14. Expand "Show Advanced Settings"
15. Ensure both "Response" and "Assertion Signature" are `Signed`
16. Add a "Signature Certificate" PEM file by clicking "Browse files…",
created [above](#Save the current PDC keys in a PEM file)
17. Add Attribute Statements (case sensitive, use the dropdown for each Value):
– Map `firstName`, `Basic` to `user.firstName`
– Map `lastName`, `Basic` to `user.lastName`

18. Click "Next"
19. Click "Finish"
20. Send Okta's SAML "Metadata URL" value to the PDC team.

The PDC team will use this URL to configure an Identity Provider (IdP) within
PDC Keycloak and link it to a PDC Keycloak organization such that when users log
into PDC they will be redirected to their canonical IdP based on the domain name
in the email address. For example, entering "
[email protected]" should
redirect the user to Okta. [Okta
configuration](https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-assign-apps.htm)
will determine whether a myfoundation user can log into the PDC. If
"
[email protected]" has been assigned in Okta, then the Okta-configured
login procedure will be used for authentication, and if successful, the user
will be redirected to PDC Keycloak and be granted a valid PDC session.
## Google Workspace Configuration using SAML 2.0
As of this writing, Google Workspace seems to support SAML 2.0 and not OIDC.
### In Google Workspace
Via https://support.google.com/a/answer/6087519?sjid=14379173059534913826-NA#zippy=%2Cstep-add-the-custom-saml-app
1. Visit https://admin.google.com and log in as a super-administrator user.
2. Visit https://admin.google.com/ac/apps/unified
3. Click "Add App" -> "Add custom SAML app"
4. Set "App name" to `Philanthropy Data Commons`
5. Set "Description" to `Allows login to the PDC using this Google Workspace`
6. Set "App icon" to the PDC logo
7. Click "Continue"
8. Click "DOWNLOAD METADATA" and save the XML file
9. Click "Continue"
Send the metadata XML file to the person helping with integration.
### In PDC Keycloak
1. Visit the Keycloak admin console
2. In the PDC realm, visit "Identity providers"
3. Click "Add Identity Provider" of type "SAML v2.0." If none are present such
that "Add Identity Provider" is not available, click "SAML v2.0" under "User
defined"
4. Set the "Alias" to the descriptive, simple, unique alias named above, e.g.
`foundation-google-saml`, **Important**: this alias sets the broker or
"Single Sign-on URL" used by Google for integration and therefore must match
the "Single Sign-on URL" configured in Google Workspace
5. Set "Use entity descriptor" to "Off"
6. Under "Import config from file" click "Browse"
7. Choose the metadata file downloaded from Google above
8. Ensure "NameID policy format" is set to "Email"
9. Ensure "Principal type" is set to "Subject NameID"
10. Set "Want Assertions signed" to "On"
11. Ensure "Validate signatures" is "On"
12. Set "Pass subject" to "On"
13. Set "Sync mode" to "Import"
14. Click "Save"
15. Visit the new Identity provider's Provider details
16. Write down the "Redirect URI" value and "Service provider entity ID" value
17. Click "Mappers" tab
18. Add a map from `firstName` to `firstName`:
– Click "Add mapper"
– Set "Name" to `Import First Name`
– Leave "Sync mode override" as `Inherit`
– Select `Attribute Importer` from the "Mapper type" dropdown menu
– Set "Attribute Name" to `firstName` **Important:** this attribute name
must match a "Name" set in Google "App attributes" for the import to work
– Leave "Name Format" as `ATTRIBUTE_FORMAT_BASIC`
– Select `firstName` from the "User Attribute Name" dropdown
– Click "Save"
19. Add a map from `lastName` to `lastName`:
– Click "Add mapper"
– Set "Name" to `Import Last Name`
– Leave "Sync mode override" as `Inherit`
– Select `Attribute Importer` from the "Mapper type" dropdown menu
– Set "Attribute Name" to `lastName` **Important:** this attribute name must
match a "Name" set in Google "App attributes" for the import to work
– Leave "Name Format" as `ATTRIBUTE_FORMAT_BASIC`
– Select `lastName` from the "User Attribute Name" dropdown
– Click "Save".
Send the following information to the organization integrating Google:
– PDC Keycloak's "Redirect URI" (to be Google's "ACS URL")
– PDC Keycloak's "Service provider entity ID" (to be Google's "Entity ID")
Link the newly added IdP to its corresponding organization.
See also this Keycloak documentation:
https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_
1. Visit "Organizations"
2. Open the organization
3. Click the "Identity Providers" tab
4. Click "Link identity provider"
5. Select the IdP (created above) from the "Identity provider" dropdown menu
6. Select the organization's domain name from the "Domain" dropdown menu
7. Keep "Hide on login page" set to `On`
8. Set "Redirect when email domain matches" to `On`
9. Click "Save".
### In Google Workspace Again
1. Enter Keycloak's "Redirect URI" as Google's "ACS URL"
2. Enter Keycloak's "Service provider entity ID" as Google's "Entity ID"
3. Ensure "Signed response" is unchecked (assertions will still be signed)
4. Set "Name ID format" to `Email`
5. Set "Name ID" to `Basic Information > Primary email`
6. Click "Continue"
7. Under Attributes, click "Add Mapping"
8. Select "First name", set "App attributes" to `firstName` **Important:** this
attribute name must match an "Attribute Name" set in Keycloak Mappers for the
import to work.
9. Click "Add Mapping" again
10. Select "Last name", set "App attributes" to `lastName` **Important:** this
attribute name must match an "Attribute Name" set in Keycloak Mappers for
the import to work.
11. Click "Finish"
By default, User access is "OFF for everyone" so create a group for PDC access.
1. Click "Directory" on the leftmost menu
2. Click "Groups"
3. Click "Create group" or "CREATE A GROUP"
4. Set "Group name" to "PDC"
5. Set "Group email" to "pdc"
6. Set "Group description" to "Philanthropy Data Commons users"
7. Check "Security" to make it a security group to which you apply policies
8. Click "Next"
9. Set "Access type" to "Restricted"
10. Click "CREATE GROUP"
Add at least one member to the newly created PDC group.
1. From the PDC group, click "ADD MEMBERS"
2. Find and add a user by clicking "ADD TO GROUP"
Grant members of the PDC group access to log in to the PDC App.
1. Visit the ["Apps" area](https://admin.google.com/ac/apps/unified?journey=218)
2. Click the "Philanthropy Data Commons" app
3. Under "User access" click the inverted carat to expand "User access"
4. Under "Philanthropy Data Commons" click "Groups"
5. Click "Search for a group"
6. Click the "PDC" group
7. Under "Service status" click "ON"
8. Click "SAVE"
9. Visit the "Philanthropy Data Commons" app again
10. Verify that "User access" is "ON for 1 group", namely the "PDC" group
## Microsoft Entra Configuration Using Built-in Microsoft Provider
Following https://www.keycloak.org/docs/26.5.2/server_admin/index.html#_microsoft
### In Microsoft Entra
From https://entra.microsoft.com/ perform the following steps.
1. Copy or save the Tenant ID
2. Visit "App registrations"
3. Click "New registration"
4. Set "Name" to `Philanthropy Data Commons`
5. Set "Who can use this application or access this API?" to "Accounts in this
organizational directory only (Default Directory only – Single tenant)"
6. Click "Register"
7. Click "Certificates & secrets"
8. Under "Client secrets" click "New client secret"
9. Set "Description" to `PDC delegated authentication`
10. Set "Expires" to "730 days (24 months)"
11. Click "Add"
12. Copy or save the secret Value and Secret ID
13. Send Tenant ID, Application (client) ID, and secret Value to the PDC admin
Grant permission to PDC Keycloak to read user data from Microsoft.
1. Under "Manage" click "API Permissions"
2. Under "Microsoft Graph" to the right of "User.Read" click the ellipsis "…"
3. Under "Configured Permissions" click "Add a permission"
4. Click "Microsoft Graph"
5. Click "Delegated permissions"
6. Check "email", "openid", and "profile"
7. Click "Add permissions"
8. Click "Grant admin consent for Default Directory"
Restrict PDC access to specific users (or groups)
Following https://learn.microsoft.com/en-us/entra/identity-platform/howto-restrict-your-app-to-a-set-of-users
1. Click "Enterprise Apps" in the leftmost menu
2. Click "Philanthropy Data Commons" (this context differs from the above)
3. Under "Manage" click "Properties"
4. Set "Assignment required?" to "Yes"
5. Click "Save" (above the properties)
6. Under "Manage" click "Users and groups"
7. Click "Add user/group"
8. Under "Users" click "None Selected"
9. Check the users that should have access to PDC
10. Click "Select"
11. Click "Assign"
If your subscription permits, you may instead (of steps 8-9) create a PDC group,
assign users to that group, and then assign the group to the App.
### In Keycloak
1. Visit the Keycloak admin console
2. In the PDC realm, visit "Identity providers"
3. Click "Add provider"
4. Under "Social", click "Microsoft"
5. Set "Alias" to include the short name of the organization and `client`, for
example `myfoundation-microsoft-entra-client`
6. Set the display name to include the full name of the organization, for
example `My Foundation Microsoft Entra Client`
7. Set the "Client ID" to the value provided by the Entra admin (a UUID)
8. Set the "Client Secret" to the value provided by the Entra admin
9. Set "Prompt" to `login`
10. Set Tenant ID to the value provided by the Entra admin (a UUID)
11. Click "Add"
Under the newly created Identity provider,
1. Set "Scopes" to `openid profile email`
2. Set "Hide on login page" to "On"
3. Set "Show in Account console" to "When linked"
4. Set "Sync mode" to "Import"
5. Click "Save"
6. Copy or save the "Redirect URI" value
7. Send the Redirect URI to the Entra admin
Link the Organization to the newly created Identity provider:
1. Visit "Organizations"
2. Open the organization
3. Click the "Identity Providers" tab
4. Click "Link identity provider"
5. Select the IdP (created above) from the "Identity provider" dropdown menu
6. Select the organization's domain name from the "Domain" dropdown menu
7. Keep "Hide on login page" set to `On`
8. Set "Redirect when email domain matches" to `On`
9. Click "Save".
### In Microsoft Entra again
1. Visit "App registrations"
2. Click the "All applications" tab
3. Click "Philanthropy Data Commons"
4. Under "Redirect URIs" click "Add a Redirect URI"
5. Click "Add Redirect URI"
6. Click "Web"
7. Set "Redirect URI" to the value sent by the PDC admin
8. Ensure the "Implicit grant and hybrid flows" items are unchecked
9. Click "Configure"
## Keycloak Configuration
Configure the PDC realm to use organizations and set up an organization.
See also this Keycloak Documentation:
https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_organizations
1. In the PDC realm, go to "Realm Settings"
2. Set "Organizations" to `On` (if not already enabled)
3. Set "Admin Permissions" to `On`
4. Click "Save"
5. Visit "Organizations"
6. Click "Create Organization" (if not already present):
– Set "Name" to the long name of the organization, e.g. `My Foundation`
– Set "Alias" to a short name of the organization, e.g. `myfoundation`
– Set "Domain" to the organization's domain name, e.g. `myfoundation.org`
– Optionally set "Redirect URL" to the API documentation URL
7. Click "Save".
### PDC Keycloak Configuration with Okta via OIDC (preferred over SAML)
Add an OIDC Identity Provider to the PDC Realm.
See also this Keycloak documentation:
https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_identity_broker_oidc
1. Visit "Identity Providers"
2. Click "Add Provider" of type "OpenID Connect v1.0." If no existing providers
are present such that "Add Identity Provider" is not available, click "OpenID
Connect v1.0" under "User defined"
3. Set the "Alias" to the descriptive, simple, unique alias named above, e.g.
`foundation-okta-oidc`, **Important**: this alias sets the broker or
"Single Sign-on URL" used by Okta for integration and therefore must match
the "Single Sign-on URL" configured in Okta
4. Set the "Display name" to describe the organization that is herein linked
5. Under "OpenID Connect Settings" leave "Use discover endpoint" `On`
6. Set "Discovery endpoint" to the "Metadata URI" from Okta, similar to
`https://example.org/oauth2/default/.well-known/oauth-authorization-server`
7. Set "Client authentication" to `JWT signed with private key`
8. Set "Client ID" to the "Client ID" from Okta, similar to
`0oatc6chn9IXY0389697`
9. Leave "Client Secret" blank (it is not required due to using a keypair)
10. Leave "Client assertion signature algorithm" to `Algorithm not specified`
11. Leave "Client assertion audience" blank
12. Leave "Add X.509 Headers to the JWT" `Off`
13. Click "Add"
14. Under "OpenID Connect Settings", ensure "Validate Signatures" is `On`
15. Set "Use PKCE" to `On`
16. Set "PKCE Method" to `S256`
17. Expand "Advanced"
18. Set "Pass login_hint" to `On`
19. Set "Scopes" to `openid profile email`
20. Set "Trust Email" to `On`
21. Set "Hide on login page" to `On`
22. Set "Sync mode" to `Force`
23. Click "Save"
24. Click the "Mappers" tab
25. Click "Add mapper"
26. Set "Name" to `Import First Name From Profile Claim`
27. Set "Mapper type" to `Attribute Importer` (from the dropdown)
28. Set "Claim" to `profile`
29. Set "User Attribute Name" to `firstName` (from the dropdown)
30. Click "Save"
31. Click "Provider details" near the top to go back to the "Mappers" tab
32. Click "Add mapper"
33. Set "Name" to `Import Last Name From Profile Claim`
34. Set "Mapper type" to `Attribute Importer` (from the dropdown)
35. Set "Claim" to `profile`
36. Set "User Attribute Name" to `lastName` (from the dropdown)
37. Click "Save"
38. Click "Provider details" near the top to go back to the "Mappers" tab
39. Click "Add mapper"
40. Set "Name" to `Import Email Address From Email Claim`
41. Set "Mapper type" to `Attribute Importer` (from the dropdown)
42. Set "Claim" to `email`
43. Set "User Attribute Name" to `email` (from the dropdown)
44. Click "Save".
Link the newly added IdP to its corresponding organization.
See also this Keycloak documentation:
https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_
1. Visit "Organizations"
2. Open the organization
3. Click the "Identity Providers" tab
4. Click "Link identity provider"
5. Select the IdP (created above) from the "Identity provider" dropdown menu
6. Select the organization's domain name from the "Domain" dropdown menu
7. Keep "Hide on login page" set to `On`
8. Set "Redirect when email domain matches" to `On`
9. Click "Save".
Test the integration (see [above](#testing-an-okta-integration)).
### PDC Keycloak Configuration with Okta via SAML 2.0
Add a SAML Identity Provider to the PDC Realm.
See also this Keycloak documentation:
https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_client-saml-configuration
1. Visit "Identity Providers"
2. Click "Add Identity Provider" of type "SAML v2.0." If none are present such
that "Add Identity Provider" is not available, click "SAML v2.0" under "User
defined"
3. Set the "Alias" to the descriptive, simple, unique alias named above, e.g.
`foundation-okta-saml`, **Important**: this alias sets the broker or
"Single Sign-on URL" used by Okta for integration and therefore must match
the "Single Sign-on URL" configured in Okta
4. Set the "SAML entity descriptor" to the URL sent from the person who
configured Okta. In Okta this is called the "Metadata URL"
5. Verify that the "NameID policy format" is `Email` (if not, contact the person
who configured Okta to correct the Okta configuration, refer to Okta's step 11)
6. Set the "Principal type" to `Subject NameID`
7. Set "Want AuthnRequests signed" to `On`
8. Set "Want Assertions signed" to `On`
9. Set "Validate Signatures" to `On`
10. Set "Sign service provider metadata" to `On`
11. Set "Pass subject" to `On`
12. Set "Hide on login page" to `On`
13. Set "Sync mode" to `Force`
14. Click "Save"
15. Click the "Mappers" tab on the Identity Provider
16. Add a map from `firstName` to `firstName`:
– Click "Add mapper"
– Set "Name" to `Import First Name`
– Leave "Sync mode override" as `Inherit`
– Select `Attribute Importer` from the "Mapper type" dropdown menu
– Set "Attribute Name" to `firstName` **Important:** this attribute name
must match a "Name" set in Okta "Attribute Statements (optional)" for the
import to work
– Leave "Name Format" as `ATTRIBUTE_FORMAT_BASIC`
– Select `firstName` from the "User Attribute Name" dropdown
– Click "Save"
17. Add a map from `lastName` to `lastName`:
– Click "Add mapper"
– Set "Name" to `Import Last Name`
– Leave "Sync mode override" as `Inherit`
– Select `Attribute Importer` from the "Mapper type" dropdown menu
– Set "Attribute Name" to `lastName` **Important:** this attribute name must
match a "Name" set in Okta "Attribute Statements (optional)" for the
import to work
– Leave "Name Format" as `ATTRIBUTE_FORMAT_BASIC`
– Select `lastName` from the "User Attribute Name" dropdown
– Click "Save".
Link the newly added IdP to its corresponding organization.
See also this Keycloak documentation:
https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_
1. Visit "Organizations"
2. Open the organization
3. Click the "Identity Providers" tab
4. Click "Link identity provider"
5. Select the IdP (created above) from the "Identity provider" dropdown menu
6. Select the organization's domain name from the "Domain" dropdown menu
7. Keep "Hide on login page" set to `On`
8. Set "Redirect when email domain matches" to `On`
9. Click "Save".
Test the integration (see [above](#testing-an-okta-integration)).
</div><div class="gfmr-markdown-rendered" data-mermaid-bg-color="transparent" data-shiki-theme="github-dark"><h1>Organization Identity Provider Integration</h1>
<p>The PDC uses Keycloak as an Identity Provider (IdP) and/or Service Provider.</p>
<p>Organizations such as funders, data providers, and changemakers that have their<br>
own IdP can integrate with PDC using their own IdP for authentication while PDC<br>
Keycloak and PDC handle authorization within PDC.</p>
<p>This guide lists specific steps to integrate specific IdPs with PDC Keycloak.</p>
<p>Integration requires a kind of three-way handshake between an organization admin<br>
and a PDC admin before a user can log into PDC:</p>
<ol>
<li>The organization admin configures a PDC app integration and sends information<br>
to the PDC admin</li>
<li>The PDC admin adds an organization integration and sends information to the<br>
organization admin</li>
<li>The organization admin finishes the PDC app integration.</li>
</ol>
<p>Perform the steps during a live meeting between admins when practical.</p>
<p>For organizations without their own IdP, the PDC administrators can either<br>
manage a Keycloak organization on their behalf (for smaller organizations) or<br>
add a separate realm as an “external” IdP (for larger organizations). In the<br>
latter case, the integration should be configured to allow an organization<br>
member to manage user membership in that realm as if it were the organization’s<br>
own IdP. With a separate realm, the users will be “unmanaged” in the new realm<br>
and “managed” in the <code>pdc</code> realm. As of this writing, these two options are<br>
available in lieu of a future Keycloak release that includes Fine-Grained Admin<br>
Permissions (FGAP) for the Keycloak organizations capability. When FGAP is<br>
available for Keycloak organizations, the organization in the <code>pdc</code> realm should<br>
be configured to allow an organization member to administer its organization,<br>
and this should obsolete the first two options above.</p>
<h2>To Test an Integration</h2>
<p>After creating an integration (below), test it using the following steps.</p>
<ol start="0">
<li>Make sure that the user is assigned to PDC within the external IdP</li>
<li>Visit the API docs</li>
<li>Click “Authorize”</li>
<li>Click “Authorize” on the “Available authorizations” modal</li>
<li>Enter an email address with the organization’s domain</li>
<li>Verify that the browser is redirected to the correct IdP (outside PDC)</li>
<li>Authenticate (log in)</li>
<li>Verify that a redirect back (through Keycloak) to the PDC API docs occurs</li>
<li>Try an API call</li>
</ol>
<h2>External Okta Identity Providers</h2>
<p>Before integrating, the PDC team needs to name an identifying alias for each<br>
integrated system, for example <code>foundation-okta-oidc</code> or <code>foundation-okta-saml</code>,<br>
to be used to link PDC Keycloak with the external IdP.</p>
<h3>Okta Configuration using OIDC (preferred over SAML)</h3>
<p>Log in to the admin area to Start an OIDC App Integration (these steps follow<br>
<a href="https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_oidc.htm">https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_oidc.htm</a><br>
with the insertion of group steps and appendage of access policy steps).</p>
<h4>Create a PDC Group</h4>
<ol>
<li>On the left nav bar, visit “Directory” -> “Groups”</li>
<li>Click “Add group”</li>
<li>Set “Name” to <code>PDC</code></li>
<li>Set “Description” to <code>Users who may access the Philanthropy Data Commons</code></li>
<li>Click “Save”</li>
<li>Click the newly created “PDC” group</li>
<li>Click “Assign people” and add at least one user.</li>
</ol>
<h4>Create a PDC Application</h4>
<ol>
<li>
<p>On the left nav bar, visit “Applications” -> “Applications”</p>
</li>
<li>
<p>Click “Create App Integration”</p>
<p><img src="https://philanthropydatacommons.org/wp-content/uploads/2026/02/okta_create_app_integration.png" alt="Create App Integration"></p>
</li>
<li>
<p>Click “OIDC”</p>
</li>
<li>
<p>Select “Web Application”</p>
</li>
<li>
<p>Click “Next”</p>
</li>
<li>
<p>Add “App Name” of <code>Philanthropy Data Commons</code></p>
</li>
<li>
<p>Leave “Proof of possession” unchecked</p>
</li>
<li>
<p>Set “Grant type” to <code>Authorization code</code> only</p>
</li>
<li>
<p>Set “Sign-in redirect URI” to the endpoint provided by the PDC team, similar<br>
to <code>https://example.org/realms/pdc/broker/foundation-okta-oidc/endpoint</code><br>
<strong>Important</strong>: the name following <code>broker/</code> here needs to match the agreed<br>
alias mentioned above</p>
</li>
<li>
<p>Clear the “Sign-out redirect URIs” by clicking the X</p>
</li>
<li>
<p>Under “Assignments” select <code>Limit access to selected groups</code></p>
</li>
<li>
<p>Set the “Selected group(s)” to the <code>PDC</code> group created earlier</p>
</li>
<li>
<p>Click “Save”</p>
</li>
<li>
<p>Confirm under “Login” that “Login initiated by” is <code>App Only</code></p>
</li>
<li>
<p>Share the “Client ID” from “Client Credentials” with the PDC team</p>
</li>
<li>
<p>Under “Client Credentials” click “Edit”</p>
</li>
<li>
<p>Set “Client authentication” to <code>Public key / Private key</code></p>
</li>
<li>
<p>Check “Require PKCE as additional verification”</p>
</li>
<li>
<p>Under “Public Keys” -> “Configuration”, check “Use a URL to fetch keys…”</p>
</li>
<li>
<p>Set the URL to the JWKS URL of the PDC Keycloak server, provided by the PDC<br>
team, similar to<br>
<code>https://example.org/realms/pdc/protocol/openid-connect/certs</code></p>
</li>
<li>
<p>Click “Save”</p>
</li>
<li>
<p>Click “Save” at an “Existing client secrets will no longer be used” warning.</p>
</li>
</ol>
<h4>Create an Access Policy and Rule for the Authorization Server</h4>
<ol>
<li>On the left nav bar, visit “Security” -> “API” (way down there)</li>
<li>Click the desired Authorization Server name, usually “default”</li>
<li>Copy the “Metadata URI” value and send it to the PDC team</li>
<li>Click the “Access Policies” tab</li>
<li>Click “Add New Access Policy”</li>
<li>Set “Name” to <code>PDC</code></li>
<li>Set “Description” to <code>Allow users to authenticate to PDC</code></li>
<li>Set “Assign to” to <code>The following clients:</code></li>
<li>Type <code>P</code> in the input box and then pick the “PDC” client created above</li>
<li>Click “Create Policy”</li>
<li>Under the new PDC policy, click “Add rule”</li>
<li>Set the “Rule Name” to <code>Issue tokens to users authenticating to PDC</code></li>
<li>Reduce the token lifetimes such as to <code>5 minutes</code> (access) and <code>90 minutes</code></li>
<li>Click “Create rule”.</li>
</ol>
<h3>Okta Configuration using SAML 2.0</h3>
<h4>Save the current PDC keys in a PEM file</h4>
<ol>
<li>Visit the PDC Keycloak SAML configuration URL, similar to<br>
<code>https://example.org/realms/pdc/protocol/saml/descriptor</code></li>
<li>Within the XML document presented, copy and paste each PEM-encoded value<br>
under “<md:KeyDescriptor use=‘signing’>…<a href="X509Certificate">ds:X509Certificate</a>”, similar to<br>
<code>MIIC...=</code>, into a single (new) text file.</li>
<li>Surround each of the values from above with PEM headers and footers, namely<br>
<code>-----BEGIN CERTIFICATE-----</code> and <code>-----END CERTIFICATE-----</code>, each on their<br>
own lines.</li>
<li>Line-wrap each of the values from above at 64 characters, according to<br>
<a href="https://www.rfc-editor.org/rfc/rfc7468.html#page-5">https://www.rfc-editor.org/rfc/rfc7468.html#page-5</a></li>
<li>Save the new file with a <code>.crt</code> extension, such as <code>pdc_signing_keys.crt</code>.</li>
</ol>
<p>This file will be used below to configure signature validation. When using SAML<br>
with Okta, there is no option to dynamically fetch these keys. So when PDC keys<br>
are updated, the integration will not work until re-uploading the PDC keys. Thus<br>
[OIDC is preferred](#Okta Configuration using OIDC (preferred over SAML)) when<br>
using Okta.</p>
<h4>Configure Okta App Integration</h4>
<ol>
<li>
<p>Log in to the admin area to Start a SAML App Integration (these steps follow<br>
<a href="https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_saml.htm">https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_saml.htm</a><br>
)</p>
</li>
<li>
<p>On the left nav bar, visit “Applications” -> “Applications”</p>
</li>
<li>
<p>Click “Create App Integration”</p>
<p><img src="https://philanthropydatacommons.org/wp-content/uploads/2026/02/okta_create_app_integration.png" alt="Create App Integration"></p>
</li>
<li>
<p>Click “SAML 2.0”</p>
<p><img src="https://philanthropydatacommons.org/wp-content/uploads/2026/02/okta_create_a_new_app_integration_SAML.png" alt="SAML 2.0"></p>
</li>
<li>
<p>Click “Next”</p>
</li>
<li>
<p>Set “App Name” to <code>Philanthropy Data Commons</code></p>
</li>
<li>
<p>If you wish to add a logo, one may be found on the <a href="https://philanthropydatacommons.org/">PDC website</a></p>
</li>
<li>
<p>Check “Do not display application icon to users” under “App visibility” to<br>
avoid erroneous IdP-initiated login attempts (because users begin the login<br>
flow from PDC Apps and not from the Okta IdP)</p>
</li>
<li>
<p>Click “Next”</p>
</li>
<li>
<p>Paste the Single sign-on URL endpoint provided by the PDC team, similar to<br>
<code>https://example.org/realms/pdc/broker/foundation-okta-saml/endpoint</code><br>
into Okta’s “Single sign-on URL”</p>
</li>
<li>
<p>Paste the “SP Entity ID URL” provided by the PDC team, similar to<br>
<code>https://example.org/realms/pdc</code> into Okta’s “Audience URI (SP Entity ID)”<br>
field</p>
</li>
<li>
<p>Set the “Name ID format” to <code>EmailAddress</code></p>
</li>
<li>
<p>Set the “Application username” to <code>Email</code></p>
</li>
<li>
<p>Expand “Show Advanced Settings”</p>
</li>
<li>
<p>Ensure both “Response” and “Assertion Signature” are <code>Signed</code></p>
</li>
<li>
<p>Add a “Signature Certificate” PEM file by clicking “Browse files…”,<br>
created [above](#Save the current PDC keys in a PEM file)</p>
</li>
<li>
<p>Add Attribute Statements (case sensitive, use the dropdown for each Value):</p>
<ul>
<li>Map <code>firstName</code>, <code>Basic</code> to <code>user.firstName</code></li>
<li>Map <code>lastName</code>, <code>Basic</code> to <code>user.lastName</code></li>
</ul>
<p><img src="https://philanthropydatacommons.org/wp-content/uploads/2026/02/okta_attribute_statements.png" alt="Attribute Statements map"></p>
</li>
<li>
<p>Click “Next”</p>
</li>
<li>
<p>Click “Finish”</p>
</li>
<li>
<p>Send Okta’s SAML “Metadata URL” value to the PDC team.</p>
<p><img src="https://philanthropydatacommons.org/wp-content/uploads/2026/02/okta_metadata_url.png" alt="SAML Metadata URL"></p>
</li>
</ol>
<p>The PDC team will use this URL to configure an Identity Provider (IdP) within<br>
PDC Keycloak and link it to a PDC Keycloak organization such that when users log<br>
into PDC they will be redirected to their canonical IdP based on the domain name<br>
in the email address. For example, entering “<a href="mailto:
[email protected]">
[email protected]</a>” should<br>
redirect the user to Okta. <a href="https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-assign-apps.htm">Okta<br>
configuration</a><br>
will determine whether a myfoundation user can log into the PDC. If<br>
“<a href="mailto:
[email protected]">
[email protected]</a>” has been assigned in Okta, then the Okta-configured<br>
login procedure will be used for authentication, and if successful, the user<br>
will be redirected to PDC Keycloak and be granted a valid PDC session.</p>
<h2>Google Workspace Configuration using SAML 2.0</h2>
<p>As of this writing, Google Workspace seems to support SAML 2.0 and not OIDC.</p>
<h3>In Google Workspace</h3>
<p>Via <a href="https://support.google.com/a/answer/6087519?sjid=14379173059534913826-NA#zippy=%2Cstep-add-the-custom-saml-app">https://support.google.com/a/answer/6087519?sjid=14379173059534913826-NA#zippy=%2Cstep-add-the-custom-saml-app</a></p>
<ol>
<li>Visit <a href="https://admin.google.com">https://admin.google.com</a> and log in as a super-administrator user.</li>
<li>Visit <a href="https://admin.google.com/ac/apps/unified">https://admin.google.com/ac/apps/unified</a></li>
<li>Click “Add App” -> “Add custom SAML app”</li>
<li>Set “App name” to <code>Philanthropy Data Commons</code></li>
<li>Set “Description” to <code>Allows login to the PDC using this Google Workspace</code></li>
<li>Set “App icon” to the PDC logo</li>
<li>Click “Continue”</li>
<li>Click “DOWNLOAD METADATA” and save the XML file</li>
<li>Click “Continue”</li>
</ol>
<p>Send the metadata XML file to the person helping with integration.</p>
<h3>In PDC Keycloak</h3>
<ol>
<li>Visit the Keycloak admin console</li>
<li>In the PDC realm, visit “Identity providers”</li>
<li>Click “Add Identity Provider” of type “SAML v2.0.” If none are present such<br>
that “Add Identity Provider” is not available, click “SAML v2.0” under “User<br>
defined”</li>
<li>Set the “Alias” to the descriptive, simple, unique alias named above, e.g.<br>
<code>foundation-google-saml</code>, <strong>Important</strong>: this alias sets the broker or<br>
“Single Sign-on URL” used by Google for integration and therefore must match<br>
the “Single Sign-on URL” configured in Google Workspace</li>
<li>Set “Use entity descriptor” to “Off”</li>
<li>Under “Import config from file” click “Browse”</li>
<li>Choose the metadata file downloaded from Google above</li>
<li>Ensure “NameID policy format” is set to “Email”</li>
<li>Ensure “Principal type” is set to “Subject NameID”</li>
<li>Set “Want Assertions signed” to “On”</li>
<li>Ensure “Validate signatures” is “On”</li>
<li>Set “Pass subject” to “On”</li>
<li>Set “Sync mode” to “Import”</li>
<li>Click “Save”</li>
<li>Visit the new Identity provider’s Provider details</li>
<li>Write down the “Redirect URI” value and “Service provider entity ID” value</li>
<li>Click “Mappers” tab</li>
<li>Add a map from <code>firstName</code> to <code>firstName</code>:
<ul>
<li>Click “Add mapper”</li>
<li>Set “Name” to <code>Import First Name</code></li>
<li>Leave “Sync mode override” as <code>Inherit</code></li>
<li>Select <code>Attribute Importer</code> from the “Mapper type” dropdown menu</li>
<li>Set “Attribute Name” to <code>firstName</code> <strong>Important:</strong> this attribute name<br>
must match a “Name” set in Google “App attributes” for the import to work</li>
<li>Leave “Name Format” as <code>ATTRIBUTE_FORMAT_BASIC</code></li>
<li>Select <code>firstName</code> from the “User Attribute Name” dropdown</li>
<li>Click “Save”</li>
</ul>
</li>
<li>Add a map from <code>lastName</code> to <code>lastName</code>:
<ul>
<li>Click “Add mapper”</li>
<li>Set “Name” to <code>Import Last Name</code></li>
<li>Leave “Sync mode override” as <code>Inherit</code></li>
<li>Select <code>Attribute Importer</code> from the “Mapper type” dropdown menu</li>
<li>Set “Attribute Name” to <code>lastName</code> <strong>Important:</strong> this attribute name must<br>
match a “Name” set in Google “App attributes” for the import to work</li>
<li>Leave “Name Format” as <code>ATTRIBUTE_FORMAT_BASIC</code></li>
<li>Select <code>lastName</code> from the “User Attribute Name” dropdown</li>
<li>Click “Save”.</li>
</ul>
</li>
</ol>
<p>Send the following information to the organization integrating Google:</p>
<ul>
<li>PDC Keycloak’s “Redirect URI” (to be Google’s “ACS URL”)</li>
<li>PDC Keycloak’s “Service provider entity ID” (to be Google’s “Entity ID”)</li>
</ul>
<p>Link the newly added IdP to its corresponding organization.</p>
<p>See also this Keycloak documentation:<br>
<a href="https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_">https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_</a></p>
<ol>
<li>Visit “Organizations”</li>
<li>Open the organization</li>
<li>Click the “Identity Providers” tab</li>
<li>Click “Link identity provider”</li>
<li>Select the IdP (created above) from the “Identity provider” dropdown menu</li>
<li>Select the organization’s domain name from the “Domain” dropdown menu</li>
<li>Keep “Hide on login page” set to <code>On</code></li>
<li>Set “Redirect when email domain matches” to <code>On</code></li>
<li>Click “Save”.</li>
</ol>
<h3>In Google Workspace Again</h3>
<ol>
<li>Enter Keycloak’s “Redirect URI” as Google’s “ACS URL”</li>
<li>Enter Keycloak’s “Service provider entity ID” as Google’s “Entity ID”</li>
<li>Ensure “Signed response” is unchecked (assertions will still be signed)</li>
<li>Set “Name ID format” to <code>Email</code></li>
<li>Set “Name ID” to <code>Basic Information > Primary email</code></li>
<li>Click “Continue”</li>
<li>Under Attributes, click “Add Mapping”</li>
<li>Select “First name”, set “App attributes” to <code>firstName</code> <strong>Important:</strong> this<br>
attribute name must match an “Attribute Name” set in Keycloak Mappers for the<br>
import to work.</li>
<li>Click “Add Mapping” again</li>
<li>Select “Last name”, set “App attributes” to <code>lastName</code> <strong>Important:</strong> this<br>
attribute name must match an “Attribute Name” set in Keycloak Mappers for<br>
the import to work.</li>
<li>Click “Finish”</li>
</ol>
<p>By default, User access is “OFF for everyone” so create a group for PDC access.</p>
<ol>
<li>Click “Directory” on the leftmost menu</li>
<li>Click “Groups”</li>
<li>Click “Create group” or “CREATE A GROUP”</li>
<li>Set “Group name” to “PDC”</li>
<li>Set “Group email” to “pdc”</li>
<li>Set “Group description” to “Philanthropy Data Commons users”</li>
<li>Check “Security” to make it a security group to which you apply policies</li>
<li>Click “Next”</li>
<li>Set “Access type” to “Restricted”</li>
<li>Click “CREATE GROUP”</li>
</ol>
<p>Add at least one member to the newly created PDC group.</p>
<ol>
<li>From the PDC group, click “ADD MEMBERS”</li>
<li>Find and add a user by clicking “ADD TO GROUP”</li>
</ol>
<p>Grant members of the PDC group access to log in to the PDC App.</p>
<ol>
<li>Visit the <a href="https://admin.google.com/ac/apps/unified?journey=218">“Apps” area</a></li>
<li>Click the “Philanthropy Data Commons” app</li>
<li>Under “User access” click the inverted carat to expand “User access”</li>
<li>Under “Philanthropy Data Commons” click “Groups”</li>
<li>Click “Search for a group”</li>
<li>Click the “PDC” group</li>
<li>Under “Service status” click “ON”</li>
<li>Click “SAVE”</li>
<li>Visit the “Philanthropy Data Commons” app again</li>
<li>Verify that “User access” is “ON for 1 group”, namely the “PDC” group</li>
</ol>
<h2>Microsoft Entra Configuration Using Built-in Microsoft Provider</h2>
<p>Following <a href="https://www.keycloak.org/docs/26.5.2/server_admin/index.html#_microsoft">https://www.keycloak.org/docs/26.5.2/server_admin/index.html#_microsoft</a></p>
<h3>In Microsoft Entra</h3>
<p>From <a href="https://entra.microsoft.com/">https://entra.microsoft.com/</a> perform the following steps.</p>
<ol>
<li>Copy or save the Tenant ID</li>
<li>Visit “App registrations”</li>
<li>Click “New registration”</li>
<li>Set “Name” to <code>Philanthropy Data Commons</code></li>
<li>Set “Who can use this application or access this API?” to “Accounts in this<br>
organizational directory only (Default Directory only – Single tenant)”</li>
<li>Click “Register”</li>
<li>Click “Certificates & secrets”</li>
<li>Under “Client secrets” click “New client secret”</li>
<li>Set “Description” to <code>PDC delegated authentication</code></li>
<li>Set “Expires” to “730 days (24 months)”</li>
<li>Click “Add”</li>
<li>Copy or save the secret Value and Secret ID</li>
<li>Send Tenant ID, Application (client) ID, and secret Value to the PDC admin</li>
</ol>
<p>Grant permission to PDC Keycloak to read user data from Microsoft.</p>
<ol>
<li>Under “Manage” click “API Permissions”</li>
<li>Under “Microsoft Graph” to the right of “User.Read” click the ellipsis “…”</li>
<li>Under “Configured Permissions” click “Add a permission”</li>
<li>Click “Microsoft Graph”</li>
<li>Click “Delegated permissions”</li>
<li>Check “email”, “openid”, and “profile”</li>
<li>Click “Add permissions”</li>
<li>Click “Grant admin consent for Default Directory”</li>
</ol>
<p>Restrict PDC access to specific users (or groups)</p>
<p>Following <a href="https://learn.microsoft.com/en-us/entra/identity-platform/howto-restrict-your-app-to-a-set-of-users">https://learn.microsoft.com/en-us/entra/identity-platform/howto-restrict-your-app-to-a-set-of-users</a></p>
<ol>
<li>Click “Enterprise Apps” in the leftmost menu</li>
<li>Click “Philanthropy Data Commons” (this context differs from the above)</li>
<li>Under “Manage” click “Properties”</li>
<li>Set “Assignment required?” to “Yes”</li>
<li>Click “Save” (above the properties)</li>
<li>Under “Manage” click “Users and groups”</li>
<li>Click “Add user/group”</li>
<li>Under “Users” click “None Selected”</li>
<li>Check the users that should have access to PDC</li>
<li>Click “Select”</li>
<li>Click “Assign”</li>
</ol>
<p>If your subscription permits, you may instead (of steps 8-9) create a PDC group,<br>
assign users to that group, and then assign the group to the App.</p>
<h3>In Keycloak</h3>
<ol>
<li>Visit the Keycloak admin console</li>
<li>In the PDC realm, visit “Identity providers”</li>
<li>Click “Add provider”</li>
<li>Under “Social”, click “Microsoft”</li>
<li>Set “Alias” to include the short name of the organization and <code>client</code>, for<br>
example <code>myfoundation-microsoft-entra-client</code></li>
<li>Set the display name to include the full name of the organization, for<br>
example <code>My Foundation Microsoft Entra Client</code></li>
<li>Set the “Client ID” to the value provided by the Entra admin (a UUID)</li>
<li>Set the “Client Secret” to the value provided by the Entra admin</li>
<li>Set “Prompt” to <code>login</code></li>
<li>Set Tenant ID to the value provided by the Entra admin (a UUID)</li>
<li>Click “Add”</li>
</ol>
<p>Under the newly created Identity provider,</p>
<ol>
<li>Set “Scopes” to <code>openid profile email</code></li>
<li>Set “Hide on login page” to “On”</li>
<li>Set “Show in Account console” to “When linked”</li>
<li>Set “Sync mode” to “Import”</li>
<li>Click “Save”</li>
<li>Copy or save the “Redirect URI” value</li>
<li>Send the Redirect URI to the Entra admin</li>
</ol>
<p>Link the Organization to the newly created Identity provider:</p>
<ol>
<li>Visit “Organizations”</li>
<li>Open the organization</li>
<li>Click the “Identity Providers” tab</li>
<li>Click “Link identity provider”</li>
<li>Select the IdP (created above) from the “Identity provider” dropdown menu</li>
<li>Select the organization’s domain name from the “Domain” dropdown menu</li>
<li>Keep “Hide on login page” set to <code>On</code></li>
<li>Set “Redirect when email domain matches” to <code>On</code></li>
<li>Click “Save”.</li>
</ol>
<h3>In Microsoft Entra again</h3>
<ol>
<li>Visit “App registrations”</li>
<li>Click the “All applications” tab</li>
<li>Click “Philanthropy Data Commons”</li>
<li>Under “Redirect URIs” click “Add a Redirect URI”</li>
<li>Click “Add Redirect URI”</li>
<li>Click “Web”</li>
<li>Set “Redirect URI” to the value sent by the PDC admin</li>
<li>Ensure the “Implicit grant and hybrid flows” items are unchecked</li>
<li>Click “Configure”</li>
</ol>
<h2>Keycloak Configuration</h2>
<p>Configure the PDC realm to use organizations and set up an organization.</p>
<p>See also this Keycloak Documentation:<br>
<a href="https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_organizations">https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_organizations</a></p>
<ol>
<li>In the PDC realm, go to “Realm Settings”</li>
<li>Set “Organizations” to <code>On</code> (if not already enabled)</li>
<li>Set “Admin Permissions” to <code>On</code></li>
<li>Click “Save”</li>
<li>Visit “Organizations”</li>
<li>Click “Create Organization” (if not already present):
<ul>
<li>Set “Name” to the long name of the organization, e.g. <code>My Foundation</code></li>
<li>Set “Alias” to a short name of the organization, e.g. <code>myfoundation</code></li>
<li>Set “Domain” to the organization’s domain name, e.g. <code>myfoundation.org</code></li>
<li>Optionally set “Redirect URL” to the API documentation URL</li>
</ul>
</li>
<li>Click “Save”.</li>
</ol>
<h3>PDC Keycloak Configuration with Okta via OIDC (preferred over SAML)</h3>
<p>Add an OIDC Identity Provider to the PDC Realm.</p>
<p>See also this Keycloak documentation:<br>
<a href="https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_identity_broker_oidc">https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_identity_broker_oidc</a></p>
<ol>
<li>Visit “Identity Providers”</li>
<li>Click “Add Provider” of type “OpenID Connect v1.0.” If no existing providers<br>
are present such that “Add Identity Provider” is not available, click “OpenID<br>
Connect v1.0” under “User defined”</li>
<li>Set the “Alias” to the descriptive, simple, unique alias named above, e.g.<br>
<code>foundation-okta-oidc</code>, <strong>Important</strong>: this alias sets the broker or<br>
“Single Sign-on URL” used by Okta for integration and therefore must match<br>
the “Single Sign-on URL” configured in Okta</li>
<li>Set the “Display name” to describe the organization that is herein linked</li>
<li>Under “OpenID Connect Settings” leave “Use discover endpoint” <code>On</code></li>
<li>Set “Discovery endpoint” to the “Metadata URI” from Okta, similar to<br>
<code>https://example.org/oauth2/default/.well-known/oauth-authorization-server</code></li>
<li>Set “Client authentication” to <code>JWT signed with private key</code></li>
<li>Set “Client ID” to the “Client ID” from Okta, similar to<br>
<code>0oatc6chn9IXY0389697</code></li>
<li>Leave “Client Secret” blank (it is not required due to using a keypair)</li>
<li>Leave “Client assertion signature algorithm” to <code>Algorithm not specified</code></li>
<li>Leave “Client assertion audience” blank</li>
<li>Leave “Add X.509 Headers to the JWT” <code>Off</code></li>
<li>Click “Add”</li>
<li>Under “OpenID Connect Settings”, ensure “Validate Signatures” is <code>On</code></li>
<li>Set “Use PKCE” to <code>On</code></li>
<li>Set “PKCE Method” to <code>S256</code></li>
<li>Expand “Advanced”</li>
<li>Set “Pass login_hint” to <code>On</code></li>
<li>Set “Scopes” to <code>openid profile email</code></li>
<li>Set “Trust Email” to <code>On</code></li>
<li>Set “Hide on login page” to <code>On</code></li>
<li>Set “Sync mode” to <code>Force</code></li>
<li>Click “Save”</li>
<li>Click the “Mappers” tab</li>
<li>Click “Add mapper”</li>
<li>Set “Name” to <code>Import First Name From Profile Claim</code></li>
<li>Set “Mapper type” to <code>Attribute Importer</code> (from the dropdown)</li>
<li>Set “Claim” to <code>profile</code></li>
<li>Set “User Attribute Name” to <code>firstName</code> (from the dropdown)</li>
<li>Click “Save”</li>
<li>Click “Provider details” near the top to go back to the “Mappers” tab</li>
<li>Click “Add mapper”</li>
<li>Set “Name” to <code>Import Last Name From Profile Claim</code></li>
<li>Set “Mapper type” to <code>Attribute Importer</code> (from the dropdown)</li>
<li>Set “Claim” to <code>profile</code></li>
<li>Set “User Attribute Name” to <code>lastName</code> (from the dropdown)</li>
<li>Click “Save”</li>
<li>Click “Provider details” near the top to go back to the “Mappers” tab</li>
<li>Click “Add mapper”</li>
<li>Set “Name” to <code>Import Email Address From Email Claim</code></li>
<li>Set “Mapper type” to <code>Attribute Importer</code> (from the dropdown)</li>
<li>Set “Claim” to <code>email</code></li>
<li>Set “User Attribute Name” to <code>email</code> (from the dropdown)</li>
<li>Click “Save”.</li>
</ol>
<p>Link the newly added IdP to its corresponding organization.</p>
<p>See also this Keycloak documentation:<br>
<a href="https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_">https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_</a></p>
<ol>
<li>Visit “Organizations”</li>
<li>Open the organization</li>
<li>Click the “Identity Providers” tab</li>
<li>Click “Link identity provider”</li>
<li>Select the IdP (created above) from the “Identity provider” dropdown menu</li>
<li>Select the organization’s domain name from the “Domain” dropdown menu</li>
<li>Keep “Hide on login page” set to <code>On</code></li>
<li>Set “Redirect when email domain matches” to <code>On</code></li>
<li>Click “Save”.</li>
</ol>
<p>Test the integration (see <a href="#testing-an-okta-integration">above</a>).</p>
<h3>PDC Keycloak Configuration with Okta via SAML 2.0</h3>
<p>Add a SAML Identity Provider to the PDC Realm.</p>
<p>See also this Keycloak documentation:<br>
<a href="https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_client-saml-configuration">https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_client-saml-configuration</a></p>
<ol>
<li>Visit “Identity Providers”</li>
<li>Click “Add Identity Provider” of type “SAML v2.0.” If none are present such<br>
that “Add Identity Provider” is not available, click “SAML v2.0” under “User<br>
defined”</li>
<li>Set the “Alias” to the descriptive, simple, unique alias named above, e.g.<br>
<code>foundation-okta-saml</code>, <strong>Important</strong>: this alias sets the broker or<br>
“Single Sign-on URL” used by Okta for integration and therefore must match<br>
the “Single Sign-on URL” configured in Okta</li>
<li>Set the “SAML entity descriptor” to the URL sent from the person who<br>
configured Okta. In Okta this is called the “Metadata URL”</li>
<li>Verify that the “NameID policy format” is <code>Email</code> (if not, contact the person<br>
who configured Okta to correct the Okta configuration, refer to Okta’s step 11)</li>
<li>Set the “Principal type” to <code>Subject NameID</code></li>
<li>Set “Want AuthnRequests signed” to <code>On</code></li>
<li>Set “Want Assertions signed” to <code>On</code></li>
<li>Set “Validate Signatures” to <code>On</code></li>
<li>Set “Sign service provider metadata” to <code>On</code></li>
<li>Set “Pass subject” to <code>On</code></li>
<li>Set “Hide on login page” to <code>On</code></li>
<li>Set “Sync mode” to <code>Force</code></li>
<li>Click “Save”</li>
<li>Click the “Mappers” tab on the Identity Provider</li>
<li>Add a map from <code>firstName</code> to <code>firstName</code>:
<ul>
<li>Click “Add mapper”</li>
<li>Set “Name” to <code>Import First Name</code></li>
<li>Leave “Sync mode override” as <code>Inherit</code></li>
<li>Select <code>Attribute Importer</code> from the “Mapper type” dropdown menu</li>
<li>Set “Attribute Name” to <code>firstName</code> <strong>Important:</strong> this attribute name<br>
must match a “Name” set in Okta “Attribute Statements (optional)” for the<br>
import to work</li>
<li>Leave “Name Format” as <code>ATTRIBUTE_FORMAT_BASIC</code></li>
<li>Select <code>firstName</code> from the “User Attribute Name” dropdown</li>
<li>Click “Save”</li>
</ul>
</li>
<li>Add a map from <code>lastName</code> to <code>lastName</code>:
<ul>
<li>Click “Add mapper”</li>
<li>Set “Name” to <code>Import Last Name</code></li>
<li>Leave “Sync mode override” as <code>Inherit</code></li>
<li>Select <code>Attribute Importer</code> from the “Mapper type” dropdown menu</li>
<li>Set “Attribute Name” to <code>lastName</code> <strong>Important:</strong> this attribute name must<br>
match a “Name” set in Okta “Attribute Statements (optional)” for the<br>
import to work</li>
<li>Leave “Name Format” as <code>ATTRIBUTE_FORMAT_BASIC</code></li>
<li>Select <code>lastName</code> from the “User Attribute Name” dropdown</li>
<li>Click “Save”.</li>
</ul>
</li>
</ol>
<p>Link the newly added IdP to its corresponding organization.</p>
<p>See also this Keycloak documentation:<br>
<a href="https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_">https://www.keycloak.org/docs/26.2.5/server_admin/index.html#_managing_identity_provider_</a></p>
<ol>
<li>Visit “Organizations”</li>
<li>Open the organization</li>
<li>Click the “Identity Providers” tab</li>
<li>Click “Link identity provider”</li>
<li>Select the IdP (created above) from the “Identity provider” dropdown menu</li>
<li>Select the organization’s domain name from the “Domain” dropdown menu</li>
<li>Keep “Hide on login page” set to <code>On</code></li>
<li>Set “Redirect when email domain matches” to <code>On</code></li>
<li>Click “Save”.</li>
</ol>
<p>Test the integration (see <a href="#testing-an-okta-integration">above</a>).</p>
</div></div>