/// <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);
        }
Exemplo n.º 2
0
        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);
        }