Skip to main content

OpenID Connect

Lagoon exposes an AddOidc extension method to register an OpenID Connect provider on the server side.

NuGet reference​

Obsolete

It is no longer necessary to explicitly add the Microsoft.AspNetCore.Authentication.OpenIdConnect package when you use the AddOidc method.

Register the service​

Add the required namespaces in the Main.cs file of the server project.

Server\Main.cs
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;

In OnConfigureServices, register the OIDC provider.

Server\Main.cs
protected override void OnConfigureServices(IServiceCollection services)
{
Services.Registry.RegisterServices(services);

IConfiguration config = Configuration;
services.AddAuthentication().AddOidc("SSO", "Explicit", options =>
{
options.Authority = config["Oidc:Authority"];
options.ClientId = config["Oidc:ClientId"];
options.ClientSecret = config["Oidc:ClientSecret"];
options.CallbackPath = "/sso-callback";
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.TokenValidationParameters = new TokenValidationParameters
{
// Utilise l'adresse e-mail comme nom de l'identité ASP.NET Core.
NameClaimType = ClaimTypes.Email
};
});
}
appsettings.json
{
"Oidc": {
"Authority": "https://identity-provider.example",
"ClientId": "client-id",
"ClientSecret": "client-secret"
}
}

Okta and group management​

With Okta, add the groups scope to receive the user's groups in the returned claims.

Server\Main.cs
services.AddAuthentication().AddOidc("SSO", "Explicit", options =>
{
options.Authority = config["Oidc:Authority"];
options.ClientId = config["Oidc:ClientId"];
options.ClientSecret = config["Oidc:ClientSecret"];
options.CallbackPath = "/sso-callback";
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("groups");
options.TokenValidationParameters = new TokenValidationParameters
{
// Utilise l'adresse e-mail comme nom de l'identité ASP.NET Core.
NameClaimType = ClaimTypes.Email
};
});

The groups can then be read from the authentication context.

Server\Main.cs
protected override Task OnSignInAsync(AuthenticationContext context, ApplicationUser user)
{
string groups = context.IdentitySource.Claims?
.Where(claim => claim.Type == "groups")
.FirstOrDefault()?.Value;

return Task.CompletedTask;
}

Forced reconnection​

With OIDC, you can ask an already authenticated user to reconnect before performing a critical action. There is nothing to do on the OIDC configuration side: support is built into AddOidc.

Client side​

Call ReconnectAsync. The method opens a popup to the configured OIDC SSO. Once the process is complete, you get a Guid to pass to the backend on the endpoint that requires reconnection.

Client
private async Task DoSomethingAsync()
{
Guid? id = await App.ReconnectAsync();
if (id.HasValue)
{
List<string> data = await Http.TryGetAsync<List<string>>($"api/monController/monAction?reconnectId={id}");
}
else
{
// L'utilisateur a fermé la popup ou la reconnexion a échoué.
ShowWarning("#reconnectionFailed");
}
}

Server side​

Call ValidateReconnectionAsync with the identifier obtained from ReconnectAsync. The method throws an exception if reconnectId is not valid or does not match the identity of the connected user.

Server\Controllers\MonController.cs
[Authorize(Policy = Policies.AuthenticatedUser)]
[HttpGet]
public async Task<IEnumerable<string>> Get(string reconnectId)
{
// Vérifie que l'utilisateur s'est bien reconnecté pour cette demande.
await _app.ValidateReconnectionAsync(reconnectId);
return Array.Empty<string>();
}

Notes​

  • Forced reconnection is only supported if the configured SSO uses the OIDC protocol.
  • In development, if you use form-based authentication, you can set App:ReconnectionDisabled to true. In that case, ReconnectAsync returns an identifier and ValidateReconnectionAsync considers it valid.
  • Special case with Cognito configured to relay authentication to another OIDC IDP: specify the provider to use with Lagoon:SSOReconnectProviderName.
appsettings.Development.json
{
"App": {
"ReconnectionDisabled": true
},
"Lagoon": {
"SSOReconnectProviderName": "LeNomDuProviderConfigureDansCognito"
}
}