/// <summary> /// Starts the authentication flow asynchronous. /// </summary> /// <param name="landingPageUrl">The landing page URL.</param> /// <returns></returns> public static async Task StartAuthenticationFlowAsync(string landingPageUrl = null) { var httpContext = HttpContext.Current; var opts = Options; var tuple = await _idsService.GetDiscoveryResponseAsync(Options.Authority).ConfigureAwait(false); var disco = tuple.Item1; if (disco == null) { RedirectToError(httpContext, tuple.Item2, tuple.Item3); return; } //prepare response var response = httpContext.Response; response.Clear(); var nonceCookie = new HttpCookie(Const.NonceCookieName); var stateCookie = new HttpCookie(Const.StateCookieName); nonceCookie.Value = Guid.NewGuid().ToString().ToBase64(); nonceCookie.Expires = DateTime.Now.AddMinutes(20); nonceCookie.HttpOnly = true; stateCookie.Value = landingPageUrl ?? httpContext.Request.Url.AbsoluteUri.ToBase64(); stateCookie.Expires = nonceCookie.Expires; stateCookie.HttpOnly = true; //set cookies response.Cookies.Add(nonceCookie); response.Cookies.Add(stateCookie); //prepare authorization url var uri = httpContext.Request.Url; var scope = "openid" + (opts.Authentication.RequestRefreshKey ? " offline_access" : "") + " " + string.Join(" ", opts.Authentication.ResourceList); var url = new AuthorizeRequest(disco.AuthorizeEndpoint).CreateAuthorizeUrl( clientId: opts.ClientId, responseType: "code id_token", responseMode: "form_post", redirectUri: httpContext.BaseUrl() + opts.Authentication.SignInEndpoint, //$"{uri.Scheme}://{uri.Authority}/{opts.Authentication.SignInEndpoint}", scope: scope, nonce: nonceCookie.Value, state: stateCookie.Value ); response.Redirect(url); }
private ClaimsPrincipal TokenValidationCommon(string encodedToken, Action <TokenValidationParameters, OpenIdConnectOptions> adjustValidationParameters, out SecurityToken securityToken) { var opts = _idsService.Options; var tuple = _idsService.GetDiscoveryResponseAsync(opts.Authority).GetAwaiter().GetResult(); var disco = tuple.Item1; if (disco == null) { throw new Exception(tuple.Item3); } ///see: https://github.com/IdentityServer/IdentityServer4.Samples/blob/dev/Clients/src/MvcManual/Controllers/HomeController.cs#L81 var keys = new List <SecurityKey>(); foreach (var webKey in disco.KeySet.Keys) { var e = Base64Url.Decode(webKey.E); var n = Base64Url.Decode(webKey.N); var key = new RsaSecurityKey(new RSAParameters { Exponent = e, Modulus = n }) { KeyId = webKey.Kid }; keys.Add(key); } var tokenValidationParams = new TokenValidationParameters() { ValidAudiences = new string[] { opts.ClientId, }, ValidIssuers = opts.TrustedAuthoritiesSet.ToArray(), IssuerSigningKeys = keys, ValidateIssuerSigningKey = true, // Token will only be valid if not expired yet, with 5 minutes clock skew. ValidateLifetime = true, RequireExpirationTime = true, ClockSkew = new TimeSpan(0, 5, 0), }; //call adjuster adjustValidationParameters(tokenValidationParams, opts); var tokenHandler = new JwtSecurityTokenHandler(); tokenHandler.InboundClaimTypeMap.Clear(); var claimPrincipal = tokenHandler.ValidateToken(encodedToken, tokenValidationParams, out securityToken); return(claimPrincipal); }