예제 #1
0
        private static async Task ValidatePrincipal(CookieValidatePrincipalContext context, IHttpClientFactory httpClientFactory, ITokenDTOStore tokenDTOStore, ClientOptions options)
        {
            var tokenDTO = await tokenDTOStore.GetTokenDTOAsync();

            var jwt = tokenDTO.GetJwt();

            //if (!jwt.TryGetPayloadValue<long>(OAuth2Consts.Claim_AccessTokenExpire, out var exp))
            //{// expStr format invalid
            //    // reject principal
            //    context.RejectPrincipal();
            //    // sign user out
            //    await context.HttpContext.SignOutAsync();
            //    return;
            //}

            if (DateTimeOffset.UtcNow > jwt.ValidTo)
            {     // access token expired
                if (!string.IsNullOrWhiteSpace(tokenDTO.RefreshToken))
                { // refresh token exists
                    // send refresh token request
                    var httpClient       = httpClientFactory.CreateClient();
                    var refreshTokenResp = await httpClient.RequestRefreshTokenAsync(new RefreshTokenRequest
                    {
                        Address      = options.TokenEndpoint,
                        ClientId     = options.ClientID,
                        ClientSecret = options.ClientSecret,
                        RefreshToken = tokenDTO.RefreshToken,
                        Scope        = string.Join(OAuth2Consts.Seperator_Scope, options.Scopes)
                    });

                    if (!refreshTokenResp.IsError)
                    {// refresh success
                        await tokenDTOStore.SaveTokenDTOAsync(refreshTokenResp.Raw);

                        //context.Properties.UpdateTokenValue(OAuth2Consts.Token_Access, refreshTokenResp.AccessToken);
                        //context.Properties.UpdateTokenValue(OAuth2Consts.Token_Refresh, refreshTokenResp.RefreshToken);
                        //var expireAt = DateTimeOffset.UtcNow.AddSeconds(refreshTokenResp.ExpiresIn).ToString(OAuth2Consts.UtcTimesamp);
                        //context.Properties.UpdateTokenValue(OAuth2Consts.Token_ExpiresAt, expireAt);
                        //context.ShouldRenew = true;
                        return;
                    }
                }

                // reject principal
                context.RejectPrincipal();
                // sign user out
                await context.HttpContext.OAuth2SignOutAsync();
            }
        }
예제 #2
0
        /// <summary>
        ///  handle sign out callback request
        /// </summary>
        protected virtual async Task HandleSignOutCallbackRequestAsync(HttpContext context)
        {
            var state = context.Request.Query[OAuth2Consts.Form_State].FirstOrDefault();

            // read return url from store
            var returnUrl = await _stateStore.GetThenRemoveAsync(state);

            if (!string.IsNullOrWhiteSpace(returnUrl))
            {
                var endSessionID = context.Request.Query[OAuth2Consts.Form_EndSessionID].FirstOrDefault();
                if (string.IsNullOrWhiteSpace(endSessionID))
                {
                    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    await context.Response.WriteAsync("missing es_id");

                    return;
                }

                var tokenDTO = await _tokenDTOStore.GetTokenDTOAsync();

                if (tokenDTO != null)
                {
                    var httpClient = _httpClientFactory.CreateClient();
                    var resp       = await httpClient.PostAsync(_options.EndSessionEndpoint, new FormUrlEncodedContent(new KeyValuePair <string, string>[] {
                        new KeyValuePair <string, string>(OAuth2Consts.Form_State, state),
                        new KeyValuePair <string, string>(OAuth2Consts.Form_EndSessionID, endSessionID),
                        new KeyValuePair <string, string>(OAuth2Consts.Form_ClientID, _options.ClientID),
                        new KeyValuePair <string, string>(OAuth2Consts.Form_ClientSecret, _options.ClientSecret),
                        new KeyValuePair <string, string>(OAuth2Consts.Form_RefreshToken, tokenDTO.RefreshToken),
                    }));

                    if (!resp.IsSuccessStatusCode)
                    {
                        var body = await resp.Content.ReadAsStringAsync();

                        _logger.LogWarning("Post end session request failed [{0}]:\n{1}", resp.StatusCode, body);
                    }
                }

                // sign out & redirect to return url
                await context.OAuth2SignOutAsync();

                context.Response.Redirect(returnUrl);
                return;
            }

            context.Response.StatusCode = (int)HttpStatusCode.NotFound;
        }
예제 #3
0
        protected override async Task <OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
        {
            var tokenRequestParameters = new Dictionary <string, string>()
            {
                { OAuth2Consts.Form_ClientID, Options.ClientId },
                { OAuth2Consts.Form_RedirectUri, context.RedirectUri },
                { OAuth2Consts.Form_ClientSecret, Options.ClientSecret },
                { OAuth2Consts.Form_Code, context.Code },
                { OAuth2Consts.Form_GrantType, OAuth2Consts.GrantType_AuthorizationCode },
            };


            var tokenDTO = await _tokenDTOStore.GetTokenDTOAsync();

            if (!string.IsNullOrWhiteSpace(tokenDTO?.RefreshToken))
            {// send old refresh token to clear it
                tokenRequestParameters[OAuth2Consts.Form_RefreshToken] = tokenDTO.RefreshToken;
            }

            // PKCE https://tools.ietf.org/html/rfc7636#section-4.5, see BuildChallengeUrl
            if (context.Properties.Items.TryGetValue(OAuthConstants.CodeVerifierKey, out var codeVerifier))
            {
                tokenRequestParameters.Add(OAuthConstants.CodeVerifierKey, codeVerifier);
                context.Properties.Items.Remove(OAuthConstants.CodeVerifierKey);
            }

            var requestContent = new FormUrlEncodedContent(tokenRequestParameters);

            var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);

            requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            requestMessage.Content = requestContent;
            requestMessage.Version = Backchannel.DefaultRequestVersion;
            var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted);

            if (response.IsSuccessStatusCode)
            {
                var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
                return(OAuthTokenResponse.Success(payload));
            }
            else
            {
                var error = "OAuth token endpoint failure: " + await Display(response);

                return(OAuthTokenResponse.Failed(new Exception(error)));
            }
        }
예제 #4
0
        public async Task <IActionResult> Index()
        {
            var token = await _tokenDTOStore.GetTokenDTOAsync();

            return(View(token));
        }