diff --git a/Okta.AspNet.Test/OpenIdConnectAuthenticationOptionsBuilderShould.cs b/Okta.AspNet.Test/OpenIdConnectAuthenticationOptionsBuilderShould.cs
new file mode 100644
index 0000000..0211309
--- /dev/null
+++ b/Okta.AspNet.Test/OpenIdConnectAuthenticationOptionsBuilderShould.cs
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2018-present Okta, Inc. All rights reserved.
+// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.
+//
+
+using System.Collections.Generic;
+using FluentAssertions;
+using Microsoft.Owin.Security.OpenIdConnect;
+using Okta.AspNet.Abstractions;
+using Xunit;
+
+namespace Okta.AspNet.Test
+{
+ public class OpenIdConnectAuthenticationOptionsBuilderShould
+ {
+ [Fact]
+ public void BuildOpenIdConnectAuthenticationOptionsCorrectly()
+ {
+ var oktaMvcOptions = new OktaMvcOptions()
+ {
+ PostLogoutRedirectUri = "http://postlogout.com",
+ OktaDomain = "http://myoktadomain.com",
+ ClientId = "foo",
+ ClientSecret = "bar",
+ RedirectUri = "/redirectUri",
+ Scope = new List { "openid", "profile", "email" },
+ };
+
+ var notifications = new OpenIdConnectAuthenticationNotifications
+ {
+ RedirectToIdentityProvider = null,
+ };
+
+ var oidcOptions = OpenIdConnectAuthenticationOptionsBuilder.BuildOpenIdConnectAuthenticationOptions(
+ oktaMvcOptions,
+ notifications);
+
+ oidcOptions.ClientId.Should().Be(oktaMvcOptions.ClientId);
+ oidcOptions.ClientSecret.Should().Be(oktaMvcOptions.ClientSecret);
+ oidcOptions.PostLogoutRedirectUri.Should().Be(oktaMvcOptions.PostLogoutRedirectUri);
+
+ var issuer = UrlHelper.CreateIssuerUrl(oktaMvcOptions.OktaDomain, oktaMvcOptions.AuthorizationServerId);
+ oidcOptions.Authority.Should().Be(issuer);
+ oidcOptions.RedirectUri.Should().Be(oktaMvcOptions.RedirectUri);
+ oidcOptions.Scope.Should().Be(string.Join(" ", oktaMvcOptions.Scope));
+ }
+ }
+}
diff --git a/Okta.AspNet/OktaMiddlewareExtensions.cs b/Okta.AspNet/OktaMiddlewareExtensions.cs
index 5307713..75c8b82 100644
--- a/Okta.AspNet/OktaMiddlewareExtensions.cs
+++ b/Okta.AspNet/OktaMiddlewareExtensions.cs
@@ -81,45 +81,15 @@ private static void AddJwtBearerAuthentication(IAppBuilder app, OktaWebApiOption
private static void AddOpenIdConnectAuthentication(IAppBuilder app, OktaMvcOptions options)
{
- var issuer = UrlHelper.CreateIssuerUrl(options.OktaDomain, options.AuthorizationServerId);
- var httpClient = new HttpClient(new UserAgentHandler("okta-aspnet", typeof(OktaMiddlewareExtensions).Assembly.GetName().Version));
-
- var configurationManager = new ConfigurationManager(
- issuer + "/.well-known/openid-configuration",
- new OpenIdConnectConfigurationRetriever(),
- new HttpDocumentRetriever(httpClient));
-
- var tokenValidationParameters = new DefaultTokenValidationParameters(options, issuer)
- {
- NameClaimType = "name",
- ValidAudience = options.ClientId,
- };
-
- var tokenExchanger = new TokenExchanger(options, issuer, configurationManager);
-
// Stop the default behavior of remapping JWT claim names to legacy MS/SOAP claim names
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
- var definedScopes = options.Scope?.ToArray() ?? OktaDefaults.Scope;
- var scopeString = string.Join(" ", definedScopes);
-
- app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
+ var notifications = new OpenIdConnectAuthenticationNotifications
{
- ClientId = options.ClientId,
- ClientSecret = options.ClientSecret,
- Authority = issuer,
- RedirectUri = options.RedirectUri,
- ResponseType = OpenIdConnectResponseType.CodeIdToken,
- Scope = scopeString,
- PostLogoutRedirectUri = options.PostLogoutRedirectUri,
- TokenValidationParameters = tokenValidationParameters,
- SecurityTokenValidator = new StrictSecurityTokenValidator(),
- Notifications = new OpenIdConnectAuthenticationNotifications
- {
- AuthorizationCodeReceived = tokenExchanger.ExchangeCodeForTokenAsync,
- RedirectToIdentityProvider = BeforeRedirectToIdentityProviderAsync,
- },
- });
+ RedirectToIdentityProvider = BeforeRedirectToIdentityProviderAsync,
+ };
+
+ app.UseOpenIdConnectAuthentication(OpenIdConnectAuthenticationOptionsBuilder.BuildOpenIdConnectAuthenticationOptions(options, notifications));
}
private static Task BeforeRedirectToIdentityProviderAsync(RedirectToIdentityProviderNotification n)
diff --git a/Okta.AspNet/OpenIdConnectAuthenticationOptionsBuilder.cs b/Okta.AspNet/OpenIdConnectAuthenticationOptionsBuilder.cs
new file mode 100644
index 0000000..3ee611e
--- /dev/null
+++ b/Okta.AspNet/OpenIdConnectAuthenticationOptionsBuilder.cs
@@ -0,0 +1,62 @@
+//
+// Copyright (c) 2018-present Okta, Inc. All rights reserved.
+// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.
+//
+
+using System.Linq;
+using System.Net.Http;
+using Microsoft.IdentityModel.Protocols;
+using Microsoft.IdentityModel.Protocols.OpenIdConnect;
+using Microsoft.Owin.Security.OpenIdConnect;
+using Okta.AspNet.Abstractions;
+
+namespace Okta.AspNet
+{
+ public class OpenIdConnectAuthenticationOptionsBuilder
+ {
+ ///
+ /// Creates a new instance of OpenIdConnectAuthenticationOptions.
+ ///
+ /// The options.
+ /// The OpenIdConnectAuthenticationNotifications notifications.
+ /// A new instance of OpenIdConnectAuthenticationOptions.
+ public static OpenIdConnectAuthenticationOptions BuildOpenIdConnectAuthenticationOptions(OktaMvcOptions oktaMvcOptions, OpenIdConnectAuthenticationNotifications notifications)
+ {
+ var issuer = UrlHelper.CreateIssuerUrl(oktaMvcOptions.OktaDomain, oktaMvcOptions.AuthorizationServerId);
+ var httpClient = new HttpClient(new UserAgentHandler("okta-aspnet", typeof(OktaMiddlewareExtensions).Assembly.GetName().Version));
+
+ var configurationManager = new ConfigurationManager(
+ issuer + "/.well-known/openid-configuration",
+ new OpenIdConnectConfigurationRetriever(),
+ new HttpDocumentRetriever(httpClient));
+
+ var tokenValidationParameters = new DefaultTokenValidationParameters(oktaMvcOptions, issuer)
+ {
+ NameClaimType = "name",
+ ValidAudience = oktaMvcOptions.ClientId,
+ };
+
+ var tokenExchanger = new TokenExchanger(oktaMvcOptions, issuer, configurationManager);
+ var definedScopes = oktaMvcOptions.Scope?.ToArray() ?? OktaDefaults.Scope;
+ var scopeString = string.Join(" ", definedScopes);
+
+ return new OpenIdConnectAuthenticationOptions
+ {
+ ClientId = oktaMvcOptions.ClientId,
+ ClientSecret = oktaMvcOptions.ClientSecret,
+ Authority = issuer,
+ RedirectUri = oktaMvcOptions.RedirectUri,
+ ResponseType = OpenIdConnectResponseType.CodeIdToken,
+ Scope = scopeString,
+ PostLogoutRedirectUri = oktaMvcOptions.PostLogoutRedirectUri,
+ TokenValidationParameters = tokenValidationParameters,
+ SecurityTokenValidator = new StrictSecurityTokenValidator(),
+ Notifications = new OpenIdConnectAuthenticationNotifications
+ {
+ AuthorizationCodeReceived = tokenExchanger.ExchangeCodeForTokenAsync,
+ RedirectToIdentityProvider = notifications.RedirectToIdentityProvider,
+ },
+ };
+ }
+ }
+}
diff --git a/Okta.AspNetCore.Test/OpenIdConnectOptionsHelperShould.cs b/Okta.AspNetCore.Test/OpenIdConnectOptionsHelperShould.cs
new file mode 100644
index 0000000..c31b526
--- /dev/null
+++ b/Okta.AspNetCore.Test/OpenIdConnectOptionsHelperShould.cs
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2018-present Okta, Inc. All rights reserved.
+// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.
+//
+
+using System.Collections.Generic;
+using System.Linq;
+using FluentAssertions;
+using Microsoft.AspNetCore.Authentication.OpenIdConnect;
+using Okta.AspNet.Abstractions;
+using Xunit;
+
+namespace Okta.AspNetCore.Test
+{
+ public class OpenIdConnectOptionsHelperShould
+ {
+ [Fact]
+ public void SetOpenIdConnectsOptionsCorrectly()
+ {
+ var oktaMvcOptions = new OktaMvcOptions
+ {
+ PostLogoutRedirectUri = "http://foo.postlogout.com",
+ AuthorizationServerId = "bar",
+ ClientId = "foo",
+ ClientSecret = "baz",
+ OktaDomain = "http://myoktadomain.com",
+ GetClaimsFromUserInfoEndpoint = true,
+ CallbackPath = "/somecallbackpath",
+ Scope = new List { "openid", "profile", "email" },
+ };
+
+ var events = new OpenIdConnectEvents() { OnRedirectToIdentityProvider = null };
+
+ var oidcOptions = new OpenIdConnectOptions();
+
+ OpenIdConnectOptionsHelper.ConfigureOpenIdConnectOptions(oktaMvcOptions, events, oidcOptions);
+
+ oidcOptions.ClientId.Should().Be(oktaMvcOptions.ClientId);
+ oidcOptions.ClientSecret.Should().Be(oktaMvcOptions.ClientSecret);
+ oidcOptions.SignedOutRedirectUri.Should().Be(oktaMvcOptions.PostLogoutRedirectUri);
+ oidcOptions.GetClaimsFromUserInfoEndpoint.Should().Be(oktaMvcOptions.GetClaimsFromUserInfoEndpoint);
+ oidcOptions.CallbackPath.Value.Should().Be(oktaMvcOptions.CallbackPath);
+
+ var issuer = UrlHelper.CreateIssuerUrl(oktaMvcOptions.OktaDomain, oktaMvcOptions.AuthorizationServerId);
+ oidcOptions.Authority.Should().Be(issuer);
+
+ oidcOptions.Scope.ToList().Should().BeEquivalentTo(oktaMvcOptions.Scope);
+ oidcOptions.CallbackPath.Value.Should().Be(oktaMvcOptions.CallbackPath);
+ oidcOptions.Events.OnRedirectToIdentityProvider.Should().BeNull();
+ }
+ }
+}
diff --git a/Okta.AspNetCore/OktaAuthenticationOptionsExtensions.cs b/Okta.AspNetCore/OktaAuthenticationOptionsExtensions.cs
index db28e16..7bbf495 100644
--- a/Okta.AspNetCore/OktaAuthenticationOptionsExtensions.cs
+++ b/Okta.AspNetCore/OktaAuthenticationOptionsExtensions.cs
@@ -5,13 +5,10 @@
using System;
using System.IdentityModel.Tokens.Jwt;
-using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
-using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Okta.AspNet.Abstractions;
namespace Okta.AspNetCore
@@ -32,42 +29,14 @@ public static AuthenticationBuilder AddOktaMvc(this AuthenticationBuilder builde
private static AuthenticationBuilder AddCodeFlow(AuthenticationBuilder builder, OktaMvcOptions options)
{
- var issuer = UrlHelper.CreateIssuerUrl(options.OktaDomain, options.AuthorizationServerId);
-
- JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
-
- builder.AddOpenIdConnect(oidcOptions =>
+ var events = new OpenIdConnectEvents
{
- oidcOptions.ClientId = options.ClientId;
- oidcOptions.ClientSecret = options.ClientSecret;
- oidcOptions.Authority = issuer;
- oidcOptions.CallbackPath = new PathString(options.CallbackPath);
- oidcOptions.SignedOutCallbackPath = new PathString(OktaDefaults.SignOutCallbackPath);
- oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
- oidcOptions.GetClaimsFromUserInfoEndpoint = options.GetClaimsFromUserInfoEndpoint;
- oidcOptions.SecurityTokenValidator = new StrictSecurityTokenValidator();
- oidcOptions.SaveTokens = true;
- oidcOptions.UseTokenLifetime = false;
- oidcOptions.BackchannelHttpHandler = new UserAgentHandler("okta-aspnetcore", typeof(OktaAuthenticationOptionsExtensions).Assembly.GetName().Version);
-
- var hasDefinedScopes = options.Scope?.Any() ?? false;
- if (hasDefinedScopes)
- {
- oidcOptions.Scope.Clear();
- foreach (var scope in options.Scope)
- {
- oidcOptions.Scope.Add(scope);
- }
- }
+ OnRedirectToIdentityProvider = BeforeRedirectToIdentityProviderAsync,
+ };
- oidcOptions.TokenValidationParameters = new DefaultTokenValidationParameters(options, issuer)
- {
- ValidAudience = options.ClientId,
- NameClaimType = "name",
- };
+ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
- oidcOptions.Events.OnRedirectToIdentityProvider = BeforeRedirectToIdentityProviderAsync;
- });
+ builder.AddOpenIdConnect(oidcOptions => OpenIdConnectOptionsHelper.ConfigureOpenIdConnectOptions(options, events, oidcOptions));
return builder;
}
diff --git a/Okta.AspNetCore/OktaMvcOptions.cs b/Okta.AspNetCore/OktaMvcOptions.cs
index 7cef0b2..76614e2 100644
--- a/Okta.AspNetCore/OktaMvcOptions.cs
+++ b/Okta.AspNetCore/OktaMvcOptions.cs
@@ -15,6 +15,8 @@ public class OktaMvcOptions : AspNet.Abstractions.OktaWebOptions
public string CallbackPath { get; set; } = OktaDefaults.CallbackPath;
+ public string PostLogoutRedirectUri { get; set; }
+
public IList Scope { get; set; } = OktaDefaults.Scope;
public bool GetClaimsFromUserInfoEndpoint { get; set; } = false;
diff --git a/Okta.AspNetCore/OpenIdConnectOptionsHelper.cs b/Okta.AspNetCore/OpenIdConnectOptionsHelper.cs
new file mode 100644
index 0000000..8c8167f
--- /dev/null
+++ b/Okta.AspNetCore/OpenIdConnectOptionsHelper.cs
@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2018-present Okta, Inc. All rights reserved.
+// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.
+//
+
+using System.Linq;
+using Microsoft.AspNetCore.Authentication.OpenIdConnect;
+using Microsoft.AspNetCore.Http;
+using Microsoft.IdentityModel.Protocols.OpenIdConnect;
+using Okta.AspNet.Abstractions;
+
+namespace Okta.AspNetCore
+{
+ public class OpenIdConnectOptionsHelper
+ {
+ ///
+ /// Configure an OpenIdConnectOptions object based on user's configuration.
+ ///
+ /// The options.
+ /// The OpenIdConnect events.
+ /// The OpenIdConnectOptions to configure.
+ public static void ConfigureOpenIdConnectOptions(OktaMvcOptions oktaMvcOptions, OpenIdConnectEvents events, OpenIdConnectOptions oidcOptions)
+ {
+ var issuer = UrlHelper.CreateIssuerUrl(oktaMvcOptions.OktaDomain, oktaMvcOptions.AuthorizationServerId);
+
+ oidcOptions.ClientId = oktaMvcOptions.ClientId;
+ oidcOptions.ClientSecret = oktaMvcOptions.ClientSecret;
+ oidcOptions.Authority = issuer;
+ oidcOptions.CallbackPath = new PathString(oktaMvcOptions.CallbackPath);
+ oidcOptions.SignedOutCallbackPath = new PathString(OktaDefaults.SignOutCallbackPath);
+ oidcOptions.SignedOutRedirectUri = oktaMvcOptions.PostLogoutRedirectUri;
+ oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
+ oidcOptions.GetClaimsFromUserInfoEndpoint = oktaMvcOptions.GetClaimsFromUserInfoEndpoint;
+ oidcOptions.SecurityTokenValidator = new StrictSecurityTokenValidator();
+ oidcOptions.SaveTokens = true;
+ oidcOptions.UseTokenLifetime = false;
+ oidcOptions.BackchannelHttpHandler = new UserAgentHandler(
+ "okta-aspnetcore",
+ typeof(OktaAuthenticationOptionsExtensions).Assembly.GetName().Version);
+
+ var hasDefinedScopes = oktaMvcOptions.Scope?.Any() ?? false;
+ if (hasDefinedScopes)
+ {
+ oidcOptions.Scope.Clear();
+ foreach (var scope in oktaMvcOptions.Scope)
+ {
+ oidcOptions.Scope.Add(scope);
+ }
+ }
+
+ oidcOptions.TokenValidationParameters = new DefaultTokenValidationParameters(oktaMvcOptions, issuer)
+ {
+ ValidAudience = oktaMvcOptions.ClientId,
+ NameClaimType = "name",
+ };
+
+ oidcOptions.Events.OnRedirectToIdentityProvider = events.OnRedirectToIdentityProvider;
+ }
+ }
+}