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(); } }
/// <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; }
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))); } }
public async Task <IActionResult> Index() { var token = await _tokenDTOStore.GetTokenDTOAsync(); return(View(token)); }