OpenID Connect / Trusted identity provider
It is possible to setup a trust to an external identity provider in ShareAspace using OpenID Connect. Using this functionality will allow you to opt-out of using the ShareAspace Identity Server and ShareAspace Authorization Server for the OAuth 2.0 authorization flows and instead use a third party authentication/authorization provider.
In this setup the ShareAspace Host is configured to trust tokens signed by an external identity provider while ShareAspace Web is configured to use the external identity provider for the OAuth 2.0 code flow.
A user will retrieve the JSON Web Tokens (JWTs) from the external identity provider. When the token is used with the ShareAspace REST APIs, ShareAspace will validate the token signature using the keys provided from the trust configuration.
One example is the Microsoft identity platform that lets you configure the OAuth 2.0 flows using:
- App Registrations in Microsoft Entra ID (Azure AD)
- App Registrations in Microsoft Azure B2C
- Microsoft Server 2019/2022 AD FS
Setting up the trust
The trust can be setup directly in the Collection bootstrap settings and/or using the ShareAspace Admin APIs.
Via the APIs it is possible to edit the configuration.
Payload
Parameter | Descriptions |
---|---|
id | The unique id for the configuration. It is possible to setup multiple trusts. |
issuerUrl | The OpenID connect metadata document endpoint. This can be configured with our without the last .well-known/openid-configuration bit. e.g. for Entra Id (Azure AD), both https://login.microsoftonline.com/{tenant}/v2.0 and https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration works. Read more about the Microsoft identity platform and the OpenID connect protocol here. |
audience | (Optional) The audience value used in the signed tokens. This is same as the application id in the Entra Id (Azure AD) / B2C case. |
jwksUri | (Optional) used for configuring an additional source of public keys for validating an issued access_token . This source will be used together with the key source provided in the metadata exchange. |
overrideIssuer | (Optional) used for providing an override value on what issuer the access_token should be validated against. |
refreshInterval | (Optional) the number of hours between ShareAspace requesting a new open id configuration from the trust. Default value is 24h. |
Example:
{
"id": "external-identity",
"issuerUrl":"https://login.microsoftonline.com/1b90b763-828c-4aa4-885c-58aa98585460/v2.0",
"audience": "6626e882-9310-4193-b82b-ce95e4e43268",
"refreshInterval": 24
}
When the trust is registered ShareAspace will use the OpenID Connect metadata document endpoint to fetch the information required from the trust, like the public keys used for validating the tokens. ShareAspace will automatically refresh the metadata in order to support the rolling changes of the signing keys etc.
Bootstrap
The bootstrap payload has an array trustedIdentityProviders
Example:
{
"trustedIdentityProviders": [
{
"id": "external-identity",
"issuerUrl":"https://login.microsoftonline.com/1b90b763-828c-4aa4-885c-58aa98585460/v2.0",
"audience": "6626e882-9310-4193-b82b-ce95e4e43268",
"refreshInterval": 24
}
]
}
Using the Admin APIs
To read and update a configuration.
GET, PUT /admin/trustedIdentityProvider/{id}
Authorization: Bearer ky...
Content-Type: application/json
To register a configuration.
POST /admin/trustedIdentityProvider
Authorization: Bearer ky...
Content-Type: application/json
Example: Creating a configuration using PowerShell.
function GetAuthorizationHeader ($key, $path){
$encodedPath = [Text.Encoding]::ASCII.GetBytes($path)
$sha = New-Object System.Security.Cryptography.HMACSHA512
$sha.key = [Convert]::FromBase64String($key)
$hash = $sha.ComputeHash($encodedPath)
$hashString = [Convert]::ToBase64String($hash)
$bearerToken = $hashString.Split('=')[0]
$bearerToken = $bearerToken.Replace('+', '-')
$bearerToken = $bearerToken.Replace('/', '_')
return @{"Authorization" = ("Bearer", $bearerToken -join " ")}
}
$AdminAPIkey = "6o6aMeh...C7hEPsYMeg=="
$path = "/admin/trustedIdentityProvider"
$uri = "https://localhost:5001" + $path
$headers = GetAuthorizationHeader $AdminAPIkey $path
$body = @{
"id" = "external-identity";
"issuerUrl" = "https://login.microsoftonline.com/1b90b763-828c-4aa4-885c-58aa98585460/v2.0";
"audience" = "6626e882-9310-4193-b82b-ce95e4e43268"
} | ConvertTo-Json
$response = Invoke-WebRequest -Method Post -Uri $uri -Headers $headers -ContentType "application/json" -Body $body
Configuring ShareAspace web
config.json
To configure ShareAspace web to use the OAuth 2.0 code flow with the trusted identity provider, the config.json
file must be configured.
Setting | Description |
---|---|
apiPath | The url to the ShareAspace API (reverse proxy). On a vanilla installation when ShareAspace web is hosted on the same server as the reverse proxy, this can be set to /api . |
client_id | The id of the registered client (i.e. the client configuration used for SAs Web). |
scope | The requested authorization scope. |
response-type | The type of token(s) expected back. Should always be set to code . |
authorizationUrl | The OAuth 2.0 authorization endpoint that ShareAspace should redirect to in order to start the OAuth 2.0 flow. |
tokenUrl | The OAuth 2.0 token endpoint where the callback handler will request the access token and id token from. |
redirect_uri | The url where ShareAspace will pickup the code that will be used to request the access token. This value must be configured on the trusted provider side. For a vanilla ShareAspace Web installation the url is always https://{fqdn}/sasweb/callback.html . |
signOut_uri | (Optional) The trusted providers logout endpoint (if applicable). |
signOut_queryParam | (Optional) If applicable, the name of the query parameter that contains the redirect link after a logout has been done. ShareAspace will pass the link to the ShareAspace start page https://{fqdn}/sasweb . |
response_mode | The response mode used with the redirect_uri. |
changePasswordUri | (Optional) The OAuth 2.0 authorization endpoint that ShareAspace should redirect to in order to start the OAuth 2 flow for resetting password. Only applicable to Microsoft Azure B2C. |
changePasswordTokenUrl | (Optional, required if changePasswordUri is used). The OAuth 2.0 token endpoint where the callback handler will request the access token and id token from (for the reset password flow). Only applicable to Microsoft Azure B2C. |
externalIdentity | (Optional) Should be set to true when using external providers. The invite emails sent to invited users will not contain a link to the password registration on the ShareAspace Identity server. Instead the link in the email message will be https://{fqdn}/sasweb . |
ignoreIdTokenToAccessToken | (Optional) Boolean parameter, If set to true, the access_token issued by the identity provider will be used as the ShareAspace access_token . |
accessTokenExpireWarningTimeMinutes | (Optional, default 10) The number of minutes before the access token expires that ShareAspace web should warn the user about the toke expiration. |
Example using Microsoft Azure B2C
{
"apiPath": "/api",
"client_id": "740aa397-ef86-46ce-a330-5dbeeeea2829",
"scope": "openid email",
"response_type": "code",
"authorizationUrl": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_susi_v2/oauth2/v2.0/authorize",
"tokenUrl": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_susi_v2/oauth2/v2.0/token",
"redirect_uri": "https://esaz918.eurostep.com/sasweb/callback.html",
"signOut_uri": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_susi_v2/oauth2/v2.0/logout",
"changePasswordUri": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_reset_v2/oauth2/v2.0/authorize",
"changePasswordTokenUrl": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_reset_v2/oauth2/v2.0/token",
"application_id": "a379f5b8-2625-4972-8493-77358d53wf44",
"signOut_queryParam": "post_logout_redirect_uri",
"response_mode": "query",
"externalIdentity": true,
"accessTokenExpireWarningTimeMinutes": 10
}
web.config
In order for ShareAspace web to request access token and id token using the code provided in the OAuth 2.0 flow, the Content-Security-Policy
in the configuration file web.config
of ShareAspace web must be updated to include the domain of the identity provider. The domain is added after default-src 'self'
.
Example using Microsoft Entra Id (Azure AD) (login.microsoftonline.com)
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'self' login.microsoftonline.com; ..." />
Step-by-step guides
Microsoft Entra Id (Azure AD)
This guide will go through the steps required to use the Microsoft identity platform in Entra Id (Azure AD) with ShareAspace. The guide uses the Azure portal UI for the setup. Note that it is possible to script all these steps.
Register App
There is a set of values that we will extract during this process.
Value | Example |
---|---|
Application (client) ID | {application-client-guid} |
Directory (tenant) ID | {tenant-guid} |
OAuth 2.0 authorization endpoint (v2) | https://login.microsoftonline.com/{tenant-guid}/oauth2/v2.0/authorize |
OAuth 2.0 token endpoint (v2) | https://login.microsoftonline.com/{tenant-guid}/oauth2/v2.0/token |
OpenID Connect metadata document | https://login.microsoftonline.com/{tenant-guid}/v2.0/.well-known/openid-configuration |
Using the Azure portal, search for or navigate to the App registrations
service.
Click the New registration
button. Give the configuration a name, decide on what type of account types that should be supported.
Select Single-page application (SPA)
under Redirect URI
and provide the ShareAspace callback to be used https://[fqdn]/sasweb/callback.html
.
Click Register
.
Copy the values for Application (client) ID
and Directory (tenant) ID
from the Essentials
section. Save these for later.
Click Endpoints
.
Copy the values for OAuth 2.0 authorization endpoint (v2)
, OAuth 2.0 token endpoint (v2)
, and OpenID Connect metadata document
. Save these for later.
These are the minimum requirements for setting up the trust and configuring ShareAspace Web. For any further configuration of the app registration please refer to the Microsoft Azure documentation.
Configuring ShareAspace
Using the values from the previous section it is possible to configure ShareAspace.
Setup trust
Register the trust by either using the collection bootstrap file or the Admin APIs.
Value | Description |
---|---|
issuerUrl |
Contains the Directory (tenant) ID (tenant-guid) that was saved earlier. |
audience |
Is the Application (client) ID (application-client-guid) saved earlier. |
{
"id": "azure-ad",
"issuerUrl":"https://login.microsoftonline.com/{tenant-guid}/v2.0",
"audience": "{application-client-guid}"
}
Configure ShareAspace Web
Open config.json
under the ShareAspace Web installation folder.
Value | Description |
---|---|
client_id |
Is the Application (client) ID (application-client-guid) saved earlier. |
scope |
Set to "openid email". |
response_type |
Set to "code". |
authorizationUrl |
Is the OAuth 2.0 authorization endpoint (v2) saved earlier. |
tokenUrl |
Is the OAuuth 2.0 token endpoint (v2) saved earlier. |
signOut_uri |
Contains the Directory (tenant) ID (tenant-guid) that was saved earlier. |
signOut_queryParam |
Set to "post_logout_redirect_uri". |
externalIdentity |
Added and set to true. |
{
"apiPath": "/api",
"client_id": "{application-guid}",
"scope": "openid email",
"response_type": "code",
"authorizationUrl": "https://login.microsoftonline.com/{tenant-guid}/oauth2/v2.0/authorize",
"tokenUrl": "https://login.microsoftonline.com/{tenant-guid}/oauth2/v2.0/token",
"redirect_uri": "https://{fqdn}/sasweb/callback.html",
"signOut_uri": "https://login.microsoftonline.com/{tenant-guid}/oauth2/v2.0/logout",
"application_id": "{tenant-guid}",
"signOut_queryParam": "post_logout_redirect_uri",
"response_mode": "query",
"externalIdentity": true
}
Open web.config
under the ShareAspace Web installation folder. Add login.microsoftonline.com
to the content security policy.
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'self' login.microsoftonline.com; ..." />
The setup is now completed.
Microsoft Azure B2C
Configuring app registrations for Microsoft Azure B2C is similar to configuring the Azure AD. The main difference is the user flows available in Azure B2C. Please refer to the Microsoft Azure B2C documentation on how to mange these.
Configuration examples
Trusted identity provider:
{
"id": "azure-b2c",
"issuerUrl": "https://example.b2clogin.com/example.onmicrosoft.com/b2c_1_susi_v2/v2.0/",
"audience": "d579c6e8-f567-4dfc-9739-d3c34b12b164"
},
{
"id": "azure-b2c2",
"issuerUrl": "https://example.b2clogin.com/example.onmicrosoft.com/b2c_1_reset_v2/v2.0/",
"audience": "d579c6e8-f567-4dfc-9739-d3c34b12b164"
}
config.json:
{
"apiPath": "/api",
"client_id": "740aa397-ef86-46ce-a330-5dbeeeea2829",
"scope": "openid email",
"response_type": "code",
"authorizationUrl": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_susi_v2/oauth2/v2.0/authorize",
"tokenUrl": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_susi_v2/oauth2/v2.0/token",
"redirect_uri": "https://esaz918.eurostep.com/sasweb/callback.html",
"signOut_uri": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_susi_v2/oauth2/v2.0/logout",
"changePasswordUri": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_reset_v2/oauth2/v2.0/authorize",
"changePasswordTokenUrl": "https://EXAMPLE_123.b2clogin.com/eurostepcloudservices.onmicrosoft.com/b2c_1_reset_v2/oauth2/v2.0/token",
"application_id": "a379f5b8-2625-4972-8493-77358d53wf44",
"signOut_queryParam": "post_logout_redirect_uri",
"response_mode": "query",
"externalIdentity": true,
"accessTokenExpireWarningTimeMinutes": 10
}
Note
b2c_1_susi_v2
and b2c_1_reset_v2
in the example above are the ids of the user flows configured in Azure B2C.
web.config:
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'self' EXAMPLE_123.b2clogin.com; ..." />
Microsoft AD FS
An OpenID Connect trust can also be setup using Active Directory Federation Services (AD FS) on Microsoft Server 2016/2019/2022.
AD FS configuration
Start the AD FS Management Console and select the Application Groups
section.
Click Add Application Group
to start the setup wizard. Give the configuration a name, e.g. "ShareAspace", and select the Web browser accessing a web application
template.
Click Next
.
In the next step:
- Copy the
Client Identifier
value and save this for later. - Add the ShareAspace Web callback address under
Redirect URI
and clickAdd
.
Click Next
.
In the Apply Access Control Policy
step make the configurations that are needed (please refer to the Microsoft AD FS documentation). In this example we will use Permit everyone
.
Click Next
twice, the click Close
. The initial configuration is now done. The final step on the AD FS side of the configuration is to map the email claims for ShareAspace.
Right click on the application group that has just been created (e.g. "ShareAspace") then click Properties
.
Select the Web application
(e.g. "ShareAspace - Web application") and click Edit
. Open the Issuance Transform Rules
tab.
- Click
Add Rule
. - Select
Send LDAP Attributes as Claims
underClaim rule template
. - Click
Next
. - Set the
Claim rule name
to "email". - Select
Active Directory
underAttribute store
. - Select
E-Mail-Addresses
underLDAP Attribute
. - Select
E-Mail Address
underOutgoing Claim Type
.
- Click
Finish
then clickOK
twice.
Cross domain configuration
As the final step in the authentication/authroization flow ShareAspace web will make a POST call to AD FS in order to exchange the authorization code for the id token. This POST is made from one domain (server hosting ShareAspace web) to a second domain (domain of AD FS). Microsoft Windows Server 2019/2022 supports CORS configuration.
Enable CORS:
> Set-AdfsResponseHeaders -EnableCORS $true
Register ShareAspace web domain:
> Set-AdfsResponseHeaders -CORSTrustedOrigins https://<sas web server fqdn>
Note
If AD FS is running on Windows Server 2016 or if for some reason the CORS configuration is not allowed to be configured on AD FS it is possible to route the code exchange POST via the ShareAspace Reverse proxy. Read more here.
The AD FS configuration is done.
Configuring ShareAspace
Using the values from the previous section it is possible to configure ShareAspace.
Setup trust
Register the trust by either using the collection bootstrap file or the Admin APIs.
Value | Description |
---|---|
issuerUrl |
The OpenID Connect URL for AD FS https://<adfs server fqdn>/adfs/.well-known/openid-configuration . |
audience |
The Client Identifier (client-identifier) saved earlier. |
{
"id": "adfs",
"issuerUrl":"https://<adfs server fqdn>/adfs/.well-known/openid-configuration",
"audience": "{client-identifier}"
}
Configure ShareAspace Web
Open config.json
under the ShareAspace Web installation folder.
Value | Description |
---|---|
client_id |
Is the Client Identifier (client-identifier) saved earlier. |
scope |
Set to "openid email". |
response_type |
Set to "code". |
authorizationUrl |
The AD FS authorization URL https://<adfs server fqdn>/adfs/oauth2/authorize . |
tokenUrl |
The AD FS token URL https://<adfs server fqdn>/adfs/oauth2/token . |
signOut_uri |
The AD FS logout URL https://<adfs server fqdn>/adfs/oauth2/logout . |
signOut_queryParam |
Set to "post_logout_redirect_uri". |
externalIdentity |
Added and set to true. |
{
"apiPath": "/api",
"client_id": "{client-identifier}",
"scope": "openid email",
"response_type": "code",
"authorizationUrl": "https://<adfs server fqdn>/adfs/oauth2/authorize",
"tokenUrl": "https://<adfs server fqdn>/adfs/oauth2/token",
"redirect_uri": "https://<sas web server fqdn>/sasweb/callback.html",
"signOut_uri": "https://<adfs server fqdn>/adfs/oauth2/logout",
"application_id": "{client-identifier}",
"signOut_queryParam": "post_logout_redirect_uri",
"response_mode": "query",
"externalIdentity": true,
"accessTokenExpireWarningTimeMinutes": 10
}
Open web.config
under the ShareAspace Web installation folder. Add the AD FS server fully qualified domain name (FQDN) to the content security policy.
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'self' <adfs server fqdn>; ..." />
Route tokenUrl via ShareAspace reverse proxy
If ShareAspace web and the ShareAspace reverse proxy are both hosted on the same domain it is possible to avoid a cross domain call from ShareAspace web to the ADFS domain by routing the token request via the ShareAspace reverse proxy.
In the appsettings.json
of the ShareAspace reverse proxy - add a new route under ReverseProxy/Routes
.
"ADFSServiceRoute": {
"ClusterId": "ADFSService",
"Match": {
"Path": "/adfs-proxy/{**catch-all}"
},
"Transforms": [
{
"PathRemovePrefix": "/adfs-proxy"
}
]
}
Proxy the request by adding a new cluster under ReverseProxy/Clusters
.
"ADFSService": {
"Destinations": {
"destination1": {
"Address": "https://<adfs server fqdn>"
}
}
}
Full example:
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Trace",
"Microsoft.Hosting.Lifetime": "Trace",
"Eurostep": "Trace"
}
},
"AllowedHosts": "*",
"Kestrel": {
"Endpoints": {
"https": {
"Url": "https://localhost:6001"
}
}
},
"ReverseProxy": {
"Routes": {
"ShareAspaceRoute": {
"ClusterId": "ShareAspaceCluster",
"Match": {
"Path": "{**catch-all}"
},
"Transforms": [
{
"PathRemovePrefix": "/api"
},
{
"RequestHeadersCopy": "true"
},
{
"RequestHeaderOriginalHost": "true"
},
{
"SAs-Route": "true"
}
]
},
"ADFSServiceRoute": {
"ClusterId": "ADFSService",
"Match": {
"Path": "/adfs-proxy/{**catch-all}"
},
"Transforms": [
{
"PathRemovePrefix": "/adfs-proxy"
}
]
}
},
"Clusters": {
"ShareAspaceCluster": {
"LoadBalancingPolicy": "FirstAlphabetical",
"HttpClient": {
"DangerousAcceptAnyServerCertificate": true
},
"HealthCheck": {
"Active": {
"Enabled": "true",
"Interval": "00:00:10",
"Timeout": "00:00:10",
"Policy": "PrimarySecondary",
"Path": "/health"
}
},
"Metadata": {
"ConsecutiveFailuresHealthPolicy.Threshold": "3"
},
"Destinations": {
"ShareAspaceCluster/destination1": {
"Address": "https://esaz951web:5001"
}
}
},
"ADFSService": {
"Destinations": {
"destination1": {
"Address": "https://adfs-server-address"
}
}
}
}
}
}
Update the tokenUrl
parameter in the ShareAspace web config.json
. Instead of requesting the token from AD FS call the configured proxy at https://<sas web server fqdn>/api/adfs-proxy/adfs/oauth2/token.
{
...
"tokenUrl": "https://<sas web server fqdn>/api/adfs-proxy/adfs/oauth2/token",
...
}
Note
That with the proxy configuration it is no longer required to set the AD FS address as default-source
in the Content-Security-Policy
of the ShareAspace web web.config
file.
The setup is now completed.