SSO - Example of Auth Flow PKCE for TIs
Introduction
The opportunity for SSO with ESS products offers a simplification for users and potentially a seamless integration between ESS applications and TI products.
Our default flow is 'Auth Flow PKCE' which is typically view as good practice.
The aim of this article is to introduce TIs to one possible way of implementing this. On the plus side, there is hardly any code in the example. On the negative side, some of us prefer to understand how it actually works under the hood and the use of OWIN in MVC hides most of the hand shaking behind the scenes.
Sample Code
Here
Pre-Requisites
You will need to have a SIMS ID Login as a technical integrator (TI) and be able to create a Tile for a SSO application. At present the default will create Auth Flow PKCE and if you wish to discuss alternatives then please contact ESS-PartnerSupport@parentpay.com explaining your needs and we will respond.
You will need to set the call back URL to https://localhost:44328/account/callback.
Once the tile is created (and approved by ESS) please harvest the client id and secret.
Getting started
Please download the sample application and expand the zip. As is common with many visual studio projects, you may have to edit the CSProj file to enable the application to pick up the NuGet packages from the correct place.
<HintPath>C:\applcation samples\sso-2\SIMS_ID-SampleApps-SSO-master\source\Auth Code Flow MVC NET 4.6.1\packages\IdentityModel.1.9.2\lib\net45\IdentityModel.dll</HintPath>
Once completed the application should be runable.
Click on login
Application goes to SIMS ID and waits for a call back.
Sign in dialogue is shown with the SSO Vendor's product name.
The call back checks the response
public ActionResult Tokens()
{
var model = new DebugTokens();
if (User is ClaimsPrincipal claimsPrincipal)
{
var idTokenHandler = new JwtSecurityTokenHandler();
var idToken = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "id_token");
if (idToken != null)
{
var idJsonToken = idTokenHandler.ReadToken(idToken.Value) as JwtSecurityToken;
model.IdToken = idJsonToken;
}
var accessTokenHandler = new JwtSecurityTokenHandler();
var accessToken = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "access_token");
if (accessToken != null)
{
var accessJsonToken = accessTokenHandler.ReadToken(accessToken.Value) as JwtSecurityToken;
model.AccessToken = accessJsonToken;
}
ViewData["token"] = model.AccessToken.ToString();
}
return View(model);
}
And updates the UI
To show what comes back, click on User Tokens and it dumps the decoded token to screen.