/
OktaMiddlewareExtensions.cs
121 lines (102 loc) · 4.92 KB
/
OktaMiddlewareExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// <copyright file="OktaMiddlewareExtensions.cs" company="Okta, Inc">
// 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.
// </copyright>
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Jwt;
using Microsoft.Owin.Security.Notifications;
using Microsoft.Owin.Security.OpenIdConnect;
using Okta.AspNet.Abstractions;
using Owin;
namespace Okta.AspNet
{
public static class OktaMiddlewareExtensions
{
public static IAppBuilder UseOktaMvc(this IAppBuilder app, OktaMvcOptions options)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
new OktaMvcOptionsValidator().Validate(options);
AddOpenIdConnectAuthentication(app, options);
return app;
}
public static IAppBuilder UseOktaWebApi(this IAppBuilder app, OktaWebApiOptions options)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
new OktaWebApiOptionsValidator().Validate(options);
AddJwtBearerAuthentication(app, options);
return app;
}
private static void AddJwtBearerAuthentication(IAppBuilder app, OktaWebApiOptions 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<OpenIdConnectConfiguration>(
issuer + "/.well-known/openid-configuration",
new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever(httpClient));
// Stop the default behavior of remapping JWT claim names to legacy MS/SOAP claim names
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var signingKeyProvider = new DiscoveryDocumentSigningKeyProvider(configurationManager);
var tokenValidationParameters = new DefaultTokenValidationParameters(options, issuer)
{
ValidAudience = options.Audience,
IssuerSigningKeyResolver = (token, securityToken, keyId, validationParameters) =>
{
var signingKeys = signingKeyProvider.GetSigningKeysAsync().GetAwaiter().GetResult();
return signingKeys.Where(x => x.KeyId == keyId);
},
};
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = tokenValidationParameters,
TokenHandler = new StrictTokenHandler(),
});
}
private static void AddOpenIdConnectAuthentication(IAppBuilder app, OktaMvcOptions options)
{
// Stop the default behavior of remapping JWT claim names to legacy MS/SOAP claim names
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var notifications = new OpenIdConnectAuthenticationNotifications
{
RedirectToIdentityProvider = BeforeRedirectToIdentityProviderAsync,
};
app.UseOpenIdConnectAuthentication(OpenIdConnectAuthenticationOptionsBuilder.BuildOpenIdConnectAuthenticationOptions(options, notifications));
}
private static Task BeforeRedirectToIdentityProviderAsync(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> n)
{
// If signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
if (n.OwinContext.Authentication.User.FindFirst("id_token") != null)
{
n.ProtocolMessage.IdTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token").Value;
}
}
// Add sessionToken to provide custom login
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
{
var sessionToken = string.Empty;
n.OwinContext.Authentication.AuthenticationResponseChallenge?.Properties?.Dictionary?.TryGetValue("sessionToken", out sessionToken);
if (!string.IsNullOrEmpty(sessionToken))
{
n.ProtocolMessage.SetParameter("sessionToken", sessionToken);
}
}
return Task.FromResult(false);
}
}
}