/// <summary> /// Processes the login callback for oidc. /// </summary> /// <param name="externalResult">The result model got from the external identity server.</param> /// <param name="localClaims">The extra claims our identity server can add.</param> /// <param name="localSignInProps">Properties that the identity server can add for self use.</param> private void ProcessLoginCallbackForOidc(ExternalResult externalResult, List <Claim> localClaims, AuthenticationProperties localSignInProps) { // if the external system sent a session id claim, copy it over // so we can use it for single sign-out Claim sid = externalResult.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); if (sid != null) { localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); } // if the external provider issued an id_token, we'll keep it for signout string idToken = externalResult.IdToken; if (idToken != null) { localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } }); } }
public async Task <ExternalResult> ComputeExternalAsync(Matrix <double> m) { ExternalResult res = new ExternalResult(); byte[] bytes = await FetchBytesExternalAsync(m); int sz = m.RowCount; int origByteSize = sz * sz * FLOAT64BDEPTH; int remaining = bytes.Length - origByteSize; res.G = GetMatrixFromBytes(bytes, 0, origByteSize, sz); res.D = GetComplexVectorFromBytes(bytes, origByteSize, remaining, sz); return(res); }
private async Task <string> GetToken() { if (string.IsNullOrEmpty(_CurrentToken)) { ExternalResult <string> tokenResult = await RequestToken(); if (tokenResult.Status == ExternalResultStatus.Error) { throw new AuthenticationException(tokenResult.Message); } _CurrentToken = tokenResult.Payload; } return(_CurrentToken); }
FindUserFromExternalProvider(ExternalResult result) { // try to determine the unique id of the external user (issued by the provider) // the most common claim type for that are the sub claim and the NameIdentifier // depending on the external provider, some other claim type might be used Claim userIdClaim = result.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Subject) ?? result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier) ?? throw new Exception("Unknown userid"); // remove the user id claim so we don't include it as an extra claim if/when we provision the user List <Claim> claims = result.Claims.ToList(); claims.Remove(userIdClaim); string provider = result.Schema; string providerUserId = userIdClaim.Value; // find external user IdentityUser user = await identityUserService.FindByExternalProvider(provider, providerUserId); return(user, provider, providerUserId, claims); }
private async Task <ExternalResult <string> > RequestToken() { ExternalResult <string> tokenResult = new ExternalResult <string>() { Status = ExternalResultStatus.Error }; _logger.LogDebug("Getting authentication token..."); using HttpClient client = _httpClientFactory.CreateClient("Pims.Api.Logging"); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json)); try { using StringContent credentials = new(JsonSerializer.Serialize(new TokenRequest { Username = _config.ConnectionUser, Password = _config.ConnectionPassword }), Encoding.UTF8, MediaTypeNames.Application.Json); Uri endpoint = new Uri($"{this._config.BaseUri}/auth/token/obtain/"); HttpResponseMessage response = await client.PostAsync(endpoint, credentials).ConfigureAwait(true); string payload = await response.Content.ReadAsStringAsync().ConfigureAwait(true); this._logger.LogTrace("Response: {response}", response); switch (response.StatusCode) { case HttpStatusCode.OK: this._logger.LogTrace("Response payload: {payload}", payload); TokenResult requestTokenResult = JsonSerializer.Deserialize <TokenResult>(payload); tokenResult.Status = ExternalResultStatus.Success; tokenResult.Payload = requestTokenResult.Token; break; case HttpStatusCode.NoContent: tokenResult.Status = ExternalResultStatus.Error; tokenResult.Message = "No token was returned from the call"; break; case HttpStatusCode.Forbidden: tokenResult.Status = ExternalResultStatus.Error; tokenResult.Message = "Token request was forbidden"; break; case HttpStatusCode.BadRequest: tokenResult.Status = ExternalResultStatus.Error; tokenResult.Message = payload; break; default: tokenResult.Status = ExternalResultStatus.Error; tokenResult.Message = $"Unable to contact endpoint {endpoint}. Http status {response.StatusCode}"; break; } } catch (Exception e) { tokenResult.Status = ExternalResultStatus.Error; tokenResult.Message = "Exception obtaining a token"; this._logger.LogError("Unexpected exception obtaining a token {e}", e); } this._logger.LogDebug("Finished getting authentication token"); return(tokenResult); }
public async Task <IActionResult> Callback(string code, string state, string session_state) { // Get the return url for the frontend from the cookies. string returnUrl = HttpContext.Request.Cookies["returnUrl"]; HttpContext.Response.Cookies.Delete("returnUrl"); //Request an accesstoken and idtoken from the authority. RestClient client = new RestClient(config.FfhictOIDC.Authority + "/connect/token"); RestRequest request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); request.AddParameter("grant_type", "authorization_code"); request.AddParameter("code", code); request.AddParameter("redirect_uri", config.FfhictOIDC.RedirectUri); request.AddParameter("client_id", config.FfhictOIDC.ClientId); request.AddParameter("client_secret", config.FfhictOIDC.ClientSecret); IRestResponse response = client.Execute(request); if (response.StatusCode != HttpStatusCode.OK) { return(BadRequest("Could not validate the identity server authentication.")); } // Parse the content to get the access token. ExternalConnectToken fhictToken = JsonConvert.DeserializeObject <ExternalConnectToken>(response.Content); if (string.IsNullOrWhiteSpace(fhictToken.AccessToken)) { throw new Exception("The FHICT didn't return a correct response. Is the FHICT server accessible?", new Exception("Content:\n" + response.Content + "\n\nError:\n" + response.ErrorMessage, response.ErrorException)); } JwtSecurityToken jwt = new JwtSecurityToken(fhictToken.AccessToken); string idp = (string)jwt.Payload.FirstOrDefault(c => c.Key.Equals("idp")).Value; string iss = (string)jwt.Payload.FirstOrDefault(c => c.Key.Equals("iss")).Value; ExternalResult result = new ExternalResult { Schema = iss, Claims = jwt.Claims, ReturnUrl = returnUrl, IdToken = fhictToken.IdToken }; // lookup our user and external provider info (IdentityUser user, string provider, string providerUserId, IEnumerable <Claim> claims) = await FindUserFromExternalProvider(result); if (user == null) { //Retrieve more user information from the external source. // Get User information RestClient informationClient = new RestClient($"{iss}/connect/userinfo"); RestRequest informationRequest = new RestRequest(Method.GET); informationRequest.AddHeader("Authorization", $"Bearer {fhictToken.AccessToken}"); IRestResponse informationResponse = informationClient.Execute(informationRequest); ExternalUserInfo userinfo = JsonConvert.DeserializeObject <ExternalUserInfo>(informationResponse.Content); List <Claim> claimsList = claims.ToList(); claimsList.Add(new Claim("email", userinfo.PreferredUsername)); claimsList.Add(new Claim("idp", idp)); claimsList.Add(new Claim("name", userinfo.Name)); IdentityUser toInsertuser = new IdentityUser() { ProviderId = provider, ExternalSubjectId = providerUserId, Email = userinfo.Email, Firstname = userinfo.GivenName, Lastname = userinfo.FamilyName, Name = userinfo.Name, Username = userinfo.PreferredUsername, ExternalProfileUrl = userinfo.Profile }; // simply auto-provisions new external user user = await identityUserService.AutoProvisionUser(toInsertuser); } // this allows us to collect any additional claims or properties // for the specific protocols used and store them in the local auth cookie. // this is typically used to store data needed for signout from those protocols. List <Claim> additionalLocalClaims = new List <Claim>(); AuthenticationProperties localSignInProps = new AuthenticationProperties(); ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps); // issue authentication cookie for user IdentityServerUser isuser = new IdentityServerUser(user.SubjectId) { DisplayName = user.Name, IdentityProvider = provider, AdditionalClaims = additionalLocalClaims }; await HttpContext.SignInAsync(isuser, localSignInProps).ConfigureAwait(false); // delete temporary cookie used during external authentication await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme).ConfigureAwait(false); // check if external login is in the context of an OIDC request AuthorizationRequest context = await interaction.GetAuthorizationContextAsync(returnUrl).ConfigureAwait(false); await events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.ClientId)).ConfigureAwait(false); if (context != null) { if (await clientStore.IsPkceClientAsync(context.ClientId).ConfigureAwait(false)) { // if the client is PKCE then we assume it's native, so this change in how to // return the response is for better UX for the end user. return(this.LoadingPage("Redirect", returnUrl)); } } return(Redirect(returnUrl)); }