This tutorial shows how to use PlusAuth with ASP.NET Core and Microsoft OpenIdConnect
. If you do not have a PlusAuth account, register from here .
This tutorial follows plusauth-dotnet-starter sample project on Github. You can download and follow the tutorial via the sample project.
After you sign up or log in to PlusAuth, you need to create a client to get the necessary configuration keys in the dashboard. Go to Clients and create a client with the type of Regular Web Application
You will need your Client Id
and Client Secret
for interacting with PlusAuth. You can retrieve them from the created client's details.
When PlusAuth authenticates a user, it needs a URI to redirect back. That URI must be in your client's Redirect URI
list. If your application uses a redirect URI that is not white-listed in your PlusAuth Client, you will receive an error.
The same thing applies to the logout URIs. After the user logs out, you need a URI to be redirected.
If you are following the sample project, the Redirect URL you need to add to the Redirect URIs field is https://localhost:7200/callback
and the Logout URL you need to add to the Post Logout Redirect URIs field is https://localhost:7200/
.
Create an ASP.NET Core application or download the sample project from the link on the top of the page.
< PackageReference Include = "Microsoft.AspNetCore.Authentication.OpenIdConnect" Version = "6.0.1" />
< PackageReference Include = "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version = "6.0.1" />
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
provides hot reload support for .cshtml
files.
We will be using appsettings.Development.json
files for maintaining providing some constant values. If you are following the sample project, rename appsettings.json
to appsettings.Development.json
and replace the values accordingly.
// appsettings.Development.json
"Default" : "Information" ,
"Microsoft.AspNetCore" : "Warning"
"ClientId" : "{YOUR-PLUSAUTH-CLIENT-ID}" ,
"ClientSecret" : "{YOUR-PLUSAUTH-CLIENT-SECRET}" ,
"AuthUrl" : "https://{YOUR-PLUSAUTH-TENANT-ID}.plusauth.com"
Do not put the appsettings.Development.json
file into source control. Otherwise, your history will contain references to your client's secret.
To enable authentication with PlusAuth, edit Program.cs
in the root and add the following section to your builder.
// Add services to the container.
// Add runtime compilation for hot reload
builder.Services. AddControllersWithViews (). AddRazorRuntimeCompilation ();
builder.Services. AddAuthentication ( options =>
// If an authentication cookie is present, use it to get authentication information
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
. AddCookie () // cookie authentication middleware first
. AddOpenIdConnect ( "PlusAuth" , options =>
options.ClientId = builder.Configuration[ "Plusauth:ClientId" ];
options.ClientSecret = builder.Configuration[ "Plusauth:ClientSecret" ];
options.Authority = builder.Configuration[ "Plusauth:AuthUrl" ];
options.ResponseType = "code" ;
options.Scope. Add ( "openid" );
options.Scope. Add ( "email" );
options.Scope. Add ( "profile" );
// Get user info after authentication
options.GetClaimsFromUserInfoEndpoint = true ;
// This is important to get user information
// Map All user information into User Claims
ClaimActionCollectionMapExtensions. MapAll (options.ClaimActions);
// Set Authentication Issuer
options.ClaimsIssuer = "PlusAuth" ;
options.CallbackPath = new PathString ( "/callback" );
options.Events = new OpenIdConnectEvents
// Configure post logout redirect
// This section provides logout action for PlusAuth
OnRedirectToIdentityProviderForSignOut = ( context ) =>
// Set PlusAuth logout endpoint
var logoutUri = $"{ builder . Configuration ["Plusauth:AuthUrl"]}/oidc/logout?client_id={ builder . Configuration ["Plusauth:ClientId"]}" ;
var postLogoutUri = context.Properties.RedirectUri;
if ( ! string . IsNullOrEmpty (postLogoutUri))
if (postLogoutUri. StartsWith ( "/" ))
postLogoutUri = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + postLogoutUri;
// Return index page after logout
logoutUri += $"&post_logout_redirect_uri={ Uri . EscapeDataString ( postLogoutUri )}" ;
context.Response. Redirect (logoutUri);
context. HandleResponse ();
return Task.CompletedTask;
var app = builder. Build ();
// Use authorization to protect endpoints
The Authentication
and OpenIdConnect
services must be added before builder.Build()
section.
The OnRedirectToIdentityProviderForSignOut
event enables logout
from both PlusAuth
and application. Removing event handler disables logout from PlusAuth
.
Add AccountController
to your application to enable Login
and Logout
actions.
// Controllers/AccountController.cs
public class AccountController : Controller
public async Task Login ( string returnUrl = "/" )
await HttpContext. ChallengeAsync ( "PlusAuth" , new AuthenticationProperties () { RedirectUri = returnUrl });
public async Task Logout ()
await HttpContext. SignOutAsync ( "PlusAuth" , new AuthenticationProperties
// Indicate that PlusAuth should redirect the user after logout.
await HttpContext. SignOutAsync (CookieAuthenticationDefaults.AuthenticationScheme);
Add HomeController
to your application to serve HTML. Add the logged-in user's profile information to the model in the controller.
// Controllers/HomeController.cs
public class HomeController : Controller
private readonly ILogger < HomeController > _logger ;
public HomeController ( ILogger < HomeController > logger )
public IActionResult Index ()
public IActionResult Profile ()
[ ResponseCache ( Duration = 0 , Location = ResponseCacheLocation.None, NoStore = true )]
public IActionResult Error ()
return View ( new ErrorViewModel { RequestId = Activity.Current ? .Id ?? HttpContext.TraceIdentifier });
Create _Layout.cshtml
under Views/Shared
folder.
<!-- Views/Shared/_Layout.cshtml -->
< nav class = "navbar navbar-expand-md navbar-dark bg-dark fixed-top" >
< div class = "container-fluid" >
< a class = "navbar-brand" href = "/" >Plusauth Starter</ a >
< ul class = "nav navbar-nav navbar-right" >
@if (User.Identity != null && User.Identity.IsAuthenticated) {
< li class = "nav-item navbar-nav" >
< a class = "nav-link" asp-controller = "Home" asp-action = "Profile" >
Logged in as: @User.FindFirst("username").Value
< a class = "btn btn-link" asp-controller = "Account" asp-action = "Logout" >
< li class = "nav-item navbar-nav" >
< a class = "btn btn-link" asp-controller = "Account" asp-action = "Login" >
< main role = "main" class = "pb-3" >@RenderBody()</ main >
< script src = "~/lib/jquery/dist/jquery.min.js" ></ script >
< script src = "~/lib/bootstrap/dist/js/bootstrap.bundle.min.js" ></ script >
< script src = "~/js/site.js" asp-append-version = "true" ></ script >
@await RenderSectionAsync("Scripts", required: false)
Create Index.cshtml
under Views/Home
folder.
<!-- Views/Home/Index.cshtml -->
@{ ViewData["Title"] = "Home Page"; }
< h1 class = "display-3" >Hello, world!</ h1 >
< p >This is a template for a simple login/register system. It includes a simple
OpenID Connect Implicit Flow. To view Profile page please login.</ p >
@if (User.Identity != null && User.Identity.IsAuthenticated) {
< a class = "btn btn-success btn-lg" asp-controller = "Home" asp-action = "Profile" role = "button" >
< a class = "btn btn-primary btn-lg" asp-controller = "Account" asp-action = "Login" role = "button" >
If a user is unauthenticated, then the Login
button will be shown, else the View Profile
button is.
Create Profile.cshtml
under Views/Home
folder.
<!-- Views/Home/Profile.cshtml -->
ViewData["Title"] = "Profile";
< h3 >Welcome @User.FindFirst("username").Value!</ h3 >
< table style = "max-width: 600px" >
@foreach (var claim in User.Claims)
< td style = "padding: 8px" >@claim.Type</ td >
< td style = "padding: 8px" >@claim.Value</ td >
That's it. Start your app and point your browser to https://localhost:7200 . Follow the Log In link to log in or sign up to your PlusAuth tenant. Upon successful login or signup, you should be redirected back to the application.