/// <summary> /// Action for exchanging a JWT generated by <c>Maskinporten</c> with a new JWT for further use as authentication against rest of Altinn. /// </summary> /// <returns>The result of the action. Contains the new token if the old token was valid and could be exchanged.</returns> private async Task <ActionResult> AuthenticateMaskinportenToken(string originalToken, bool test) { try { ICollection <SecurityKey> signingKeys = await _signingKeysRetriever.GetSigningKeys(_generalSettings.GetMaskinportenWellKnownConfigEndpoint); TokenValidationParameters validationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKeys = signingKeys, ValidateIssuer = false, ValidateAudience = false, RequireExpirationTime = true, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; ClaimsPrincipal originalPrincipal = _validator.ValidateToken(originalToken, validationParameters, out _); _logger.LogInformation("Token is valid"); string issOriginal = originalPrincipal.Claims.Where(c => c.Type.Equals(IssClaimName)).Select(c => c.Value).FirstOrDefault(); if (issOriginal == null || !_generalSettings.GetMaskinportenWellKnownConfigEndpoint.Contains(issOriginal)) { _logger.LogInformation("Invalid issuer " + issOriginal); return(Unauthorized()); } string orgNumber = GetOrganisationNumberFromConsumerClaim(originalPrincipal); if (string.IsNullOrEmpty(orgNumber)) { _logger.LogInformation("Invalid consumer claim"); return(Unauthorized()); } List <Claim> claims = new List <Claim>(); foreach (Claim claim in originalPrincipal.Claims) { claims.Add(claim); } string issuer = _generalSettings.PlatformEndpoint; string org = null; if (HasServiceOwnerScope(originalPrincipal)) { org = await _organisationService.LookupOrg(orgNumber); if (org == "digdir" && test) { org = "ttd"; } if (!string.IsNullOrEmpty(org)) { claims.Add(new Claim(AltinnCoreClaimTypes.Org, org, ClaimValueTypes.String, issuer)); } } string authenticatemethod = "maskinporten"; if (!string.IsNullOrEmpty(Request.Headers["X-Altinn-EnterpriseUser-Authentication"])) { string enterpriseUserHeader = Request.Headers["X-Altinn-EnterpriseUser-Authentication"]; (UserAuthenticationResult authenticatedEnterpriseUser, ActionResult error) = await HandleEnterpriseUserLogin(enterpriseUserHeader, orgNumber); if (error != null) { return(error); } if (authenticatedEnterpriseUser != null) { authenticatemethod = "virksomhetsbruker"; string userID = authenticatedEnterpriseUser.UserID.ToString(); string username = authenticatedEnterpriseUser.Username; string partyId = authenticatedEnterpriseUser.PartyID.ToString(); claims.Add(new Claim(AltinnCoreClaimTypes.UserId, userID, ClaimValueTypes.Integer32, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.UserName, username, ClaimValueTypes.String, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.PartyID, partyId, ClaimValueTypes.Integer32, issuer)); } } claims.Add(new Claim(AltinnCoreClaimTypes.OrgNumber, orgNumber, ClaimValueTypes.Integer32, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticateMethod, authenticatemethod, ClaimValueTypes.String, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticationLevel, "3", ClaimValueTypes.Integer32, issuer)); string[] claimTypesToRemove = { "aud", "iss", "client_amr" }; foreach (string claimType in claimTypesToRemove) { Claim audClaim = claims.Find(c => c.Type == claimType); claims.Remove(audClaim); } claims.Add(new Claim("iss", issuer, ClaimValueTypes.String, issuer)); ClaimsIdentity identity = new ClaimsIdentity(OrganisationIdentity); identity.AddClaims(claims); ClaimsPrincipal principal = new ClaimsPrincipal(identity); string serializedToken = await GenerateToken(principal); return(Ok(serializedToken)); } catch (Exception ex) { _logger.LogWarning($"Organisation authentication failed. {ex.Message}"); return(Unauthorized()); } }
/// <summary> /// Action for exchanging a JWT generated by <c>Maskinporten</c> with a new JWT for further use as authentication against rest of Altinn. /// </summary> /// <returns>The result of the action. Contains the new token if the old token was valid and could be exchanged.</returns> private async Task <ActionResult> AuthenticateMaskinportenToken(string originalToken, bool test) { try { ICollection <SecurityKey> signingKeys = await _signingKeysRetriever.GetSigningKeys(_generalSettings.GetMaskinportenWellKnownConfigEndpoint); TokenValidationParameters validationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKeys = signingKeys, ValidateIssuer = false, ValidateAudience = false, RequireExpirationTime = true, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; ClaimsPrincipal originalPrincipal = _validator.ValidateToken(originalToken, validationParameters, out _); _logger.LogInformation("Token is valid"); string orgNumber = GetOrganisationNumberFromConsumerClaim(originalPrincipal); if (string.IsNullOrEmpty(orgNumber)) { _logger.LogInformation("Invalid consumer claim"); return(Unauthorized()); } List <Claim> claims = new List <Claim>(); foreach (Claim claim in originalPrincipal.Claims) { claims.Add(claim); } string org = await _organisationService.LookupOrg(orgNumber); if (org == "digdir" && test) { org = "ttd"; } string issuer = _generalSettings.PlatformEndpoint; claims.Add(new Claim(AltinnCoreClaimTypes.Org, org, ClaimValueTypes.String, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.OrgNumber, orgNumber, ClaimValueTypes.Integer32, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticateMethod, "maskinporten", ClaimValueTypes.String, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticationLevel, "3", ClaimValueTypes.Integer32, issuer)); string[] claimTypesToRemove = { "aud", "iss", "client_amr" }; foreach (string claimType in claimTypesToRemove) { Claim audClaim = claims.Find(c => c.Type == claimType); claims.Remove(audClaim); } ClaimsIdentity identity = new ClaimsIdentity(OrganisationIdentity); identity.AddClaims(claims); ClaimsPrincipal principal = new ClaimsPrincipal(identity); string serializedToken = await GenerateToken(principal); return(Ok(serializedToken)); } catch (Exception ex) { _logger.LogWarning($"Organisation authentication failed. {ex.Message}"); return(Unauthorized()); } }
public async Task <IActionResult> AuthenticateOrganisation() { string originalToken = string.Empty; string authorization = Request.Headers["Authorization"]; if (!string.IsNullOrEmpty(authorization)) { logger.LogInformation($"Getting the token from Authorization header"); if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { logger.LogInformation($"Bearer found"); originalToken = authorization.Substring("Bearer ".Length).Trim(); } } if (string.IsNullOrEmpty(originalToken)) { logger.LogInformation($"No token found"); return(Unauthorized()); } JwtSecurityTokenHandler validator = new JwtSecurityTokenHandler(); if (!validator.CanReadToken(originalToken)) { logger.LogInformation($"Unable to read token"); return(Unauthorized()); } try { ICollection <SecurityKey> signingKeys = await signingKeysRetriever.GetSigningKeys(generalSettings.GetMaskinportenWellKnownConfigEndpoint); TokenValidationParameters validationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKeys = signingKeys, ValidateIssuer = false, ValidateAudience = false, RequireExpirationTime = true, ValidateLifetime = true }; ClaimsPrincipal originalPrincipal = validator.ValidateToken(originalToken, validationParameters, out SecurityToken validatedToken); logger.LogInformation($"Token is valid"); string orgNumber = GetOrganisationNumberFromConsumerClaim(originalPrincipal); if (string.IsNullOrEmpty(orgNumber)) { logger.LogInformation("Invalid consumer claim"); return(Unauthorized()); } List <Claim> claims = new List <Claim>(); foreach (Claim claim in originalPrincipal.Claims) { claims.Add(claim); } string org = organisationRepository.LookupOrg(orgNumber); string issuer = generalSettings.GetPlatformEndpoint; claims.Add(new Claim(AltinnCoreClaimTypes.Org, org, ClaimValueTypes.String, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.OrgNumber, orgNumber, ClaimValueTypes.Integer32, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticateMethod, "maskinporten", ClaimValueTypes.String, issuer)); claims.Add(new Claim(AltinnCoreClaimTypes.AuthenticationLevel, "3", ClaimValueTypes.Integer32, issuer)); string[] claimTypesToRemove = { "aud", "iss", "client_amr" }; foreach (string claimType in claimTypesToRemove) { Claim audClaim = claims.Find(c => c.Type == claimType); claims.Remove(audClaim); } ClaimsIdentity identity = new ClaimsIdentity(OrganisationIdentity); identity.AddClaims(claims); ClaimsPrincipal principal = new ClaimsPrincipal(identity); string token = await jwtHandler.GenerateToken(principal, new TimeSpan(0, Convert.ToInt32(generalSettings.GetJwtCookieValidityTime), 0)); return(Ok(token)); } catch (Exception ex) { logger.LogWarning($"Organisation authentication failed. {ex.Message}"); return(Unauthorized()); } }