Force single-sign-on from a Client (Application)
This requires OpenId Connect protocol and it isn’t supported in Starter Edition.
There are scenarios where you might want to force a single-sign-on from a client, that has already identified the user. This requires a trust relation between the Identity Provider and the Client. The trust is established by using a shared secret (that must be protected and handled with care of course) and by configuring the client to be allowed to send a single-sign-on token.
Scenario: Internal/on-prem system that identifies users through a local AD sign-in
If an on-prem system/application has identified the users without using the Identity Provider, but wants to open an application that uses the Identity Provider to identify users, the user will not get a single-sign-on experience (since the user isn’t signed in at the Identity Provider). This can be solved if the application can create a SSO token that can be verified the Identity Provider.
Scenario: Application that uses refresh tokens for a long time
Applications that keep the user signed in by using refresh tokens to refresh the sign-in can have a signed-in user that isn’t signed in, in the Identity Provider anymore. For example if the Identity Provider is configured to keep the user signed in for 10 days and the application is confiugred for sliding refresh tokens and using them to keep the user signed in for 20 days. When this application then redirects the user to another application, the user will not ge a singe-sign-on experience.
Force a single-sign-on between applications
Authway has a non-standard support where applications can pass a SSO token that is validated by the Identity Server to force a user to be signed in.
- Create a SSO token (see below)
- Redirect the user to the application according to section 4 (“Initiating Login from a Third Party”) in OpenId Connect core specification. The iss parameter is required and should be the address to the Identiy Provider. Pass the serialized SSO token in a non-standard parameter sso_token. The sso_token must be passed on to the Identity Provider when the target application redirects the user to sign-in.
Step 2 can be completed in a non-standard way by making an agreement between the applications, as long as the sso_token is passed to the Identity Provider.
Create a SSO token
The SSO token must fullfil these requirements:
- A valid JWT token.
- Use the HS256 algorithm to sign the token.
- Hash the shared client secret with SHA256 and use a base64 encoded hashed value as key when signing the token.
- The issuer must be the client id that creates the SSO token.
- Include an audience claim with the Identity Provider as audience.
- Include an issued at (iat) claim with the time when the client created the SSO token.
- Include a sub claim with the unique identifier of the user that should be signed in.
Sample token (without signature):
{
"alg": "HS256",
"typ": "JWT"
}.
{
"sub": "FEFC9E8B-062B-DF44-FDF0-39FC52AE2B58",
"iat": 1674050819,
"iss": "TestTrustedApp",
"aud": "https://tenant.irmciam.se"
}
C# example of creating a SSO token
var subClaim = new Claim("sub", "FEFC9E8B-062B-DF44-FDF0-39FC52AE2B58"); //Get claim value from signed-in user
var clientId = "TestTrustedApp";
var clientSecret = "W7k1i3EvpYSApLj6CW7pYGkYsFTGdwJ96m0uIh64";
var authority = "https://tenant.irmciam.se";
var key = Encoding.ASCII.GetBytes(clientSecret.Sha256()); //= Client secret
var credentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new SecurityTokenDescriptor {
Subject = new ClaimsIdentity(new Claim[] { subClaim }),
Issuer = clientId,
IssuedAt = DateTime.UtcNow,
Audience = authority,
SigningCredentials = credentials
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = (JwtSecurityToken)tokenHandler.CreateToken(tokenDescriptor);
var serializedToken = tokenHandler.WriteToken(token);
public static string Sha256(this string input)
{
if (input.IsMissing()) return string.Empty;
using (var sha = SHA256.Create())
{
var bytes = Encoding.UTF8.GetBytes(input);
var hash = sha.ComputeHash(bytes);
return Convert.ToBase64String(hash);
}
}
Python example of creating a SSO token
This sample is still not verified.
This example uses of PyJWT (https://pyjwt.readthedocs.io/en/latest/usage.html).
import jwt
import base64
from hashlib import sha256
sub = "FEFC9E8B-062B-DF44-FDF0-39FC52AE2B58"
clientId = "TestTrustedApp"
clientSecret = "W7k1i3EvpYSApLj6CW7pYGkYsFTGdwJ96m0uIh64"
authority = "https://tenant.irmciam.se"
key = sha256(clientSecret.encode("utf-8"))
base64_bytes = base64.b64encode(key)
key = base64_bytes.decode("ascii")
payload = {"sub": sub, "iss": clientId, "aud": authority, "iat": 1674050819}
serializedToken = jwt.encode(payload, key, algorithm="HS256")
Limitations to be aware of
If a client passes another user, than the currently signed-in user (at the Identity Provider), the current user will be signed out at the Identity Provider, but this will not be a complete single-sign-out effecting applications until those are refreshed (because that isn’t possible to do during a sign-in).
The client must know the unique identifier of a user to be able to create the SSO token.