private async Task Check(UMAPermissionTicket permissionTicket, CancellationToken cancellationToken) { var resourceIds = permissionTicket.Records.Select(r => r.ResourceId); var umaResources = await _umaResourceRepository.FindByIdentifiers(resourceIds, cancellationToken); var unknownResources = resourceIds.Where(rid => !umaResources.Any(r => r.Id == rid)); if (unknownResources.Any()) { throw new UMAInvalidResourceException(); } var unknownScopes = permissionTicket.Records.Where(rec => !rec.Scopes.All(sc => umaResources.First(r => r.Id == rec.ResourceId).Scopes.Contains(sc))); if (unknownScopes.Any()) { throw new UMAInvalidResourceScopeException(); } }
public override async Task <IActionResult> Handle(HandlerContext context, CancellationToken cancellationToken) { try { _umaTicketGrantTypeValidator.Validate(context); var oauthClient = await AuthenticateClient(context, cancellationToken); context.SetClient(oauthClient); var ticket = context.Request.RequestData.GetTicket(); var claimTokenFormat = context.Request.RequestData.GetClaimTokenFormat(); if (string.IsNullOrWhiteSpace(claimTokenFormat)) { claimTokenFormat = _umaHostOptions.DefaultClaimTokenFormat; } var scopes = context.Request.RequestData.GetScopesFromAuthorizationRequest(); var permissionTicket = await _umaPermissionTicketHelper.GetTicket(ticket); if (permissionTicket == null) { throw new OAuthException(ErrorCodes.INVALID_GRANT, UMAErrorMessages.INVALID_TICKET); } ClaimTokenFormatFetcherResult claimTokenFormatFetcherResult = null; if (!string.IsNullOrWhiteSpace(claimTokenFormat)) { var claimTokenFormatFetcher = _claimTokenFormatFetchers.FirstOrDefault(c => c.Name == claimTokenFormat); if (claimTokenFormatFetcher == null) { throw new OAuthException(ErrorCodes.INVALID_REQUEST, string.Format(UMAErrorMessages.BAD_TOKEN_FORMAT, claimTokenFormat)); } claimTokenFormatFetcherResult = await claimTokenFormatFetcher.Fetch(context); } if (claimTokenFormatFetcherResult == null) { return(BuildError(HttpStatusCode.Unauthorized, UMAErrorCodes.REQUEST_DENIED, UMAErrorMessages.REQUEST_DENIED)); } var invalidScopes = permissionTicket.Records.Any(rec => !scopes.All(sc => rec.Scopes.Contains(sc))); if (invalidScopes) { throw new OAuthException(ErrorCodes.INVALID_SCOPE, UMAErrorMessages.INVALID_SCOPE); } var umaResources = await _umaResourceRepository.FindByIdentifiers(permissionTicket.Records.Select(r => r.ResourceId), cancellationToken); var requiredClaims = new List <UMAResourcePermissionClaim>(); foreach (var umaResource in umaResources) { foreach (var permission in umaResource.Permissions) { if (permission.Scopes.Any(sc => scopes.Contains(sc))) { var unknownClaims = permission.Claims.Where(cl => !claimTokenFormatFetcherResult.Payload.Any(c => c.Key == cl.Name)); requiredClaims.AddRange(unknownClaims); } } } if (requiredClaims.Any()) { var needInfoResult = new JObject { { "need_info", new JObject { { UMATokenRequestParameters.Ticket, permissionTicket.Id }, { "required_claims", new JArray(requiredClaims.Select(rc => new JObject { { UMAResourcePermissionNames.ClaimTokenFormat, _umaHostOptions.DefaultClaimTokenFormat }, { UMAResourcePermissionNames.ClaimType, rc.ClaimType }, { UMAResourcePermissionNames.ClaimFriendlyName, rc.FriendlyName }, { UMAResourcePermissionNames.ClaimName, rc.Name } })) }, { "redirect_uri", _umaHostOptions.OpenIdRedirectUrl } } } }; return(new ContentResult { Content = needInfoResult.ToString(), ContentType = "application/json", StatusCode = (int)HttpStatusCode.Unauthorized }); } var isNotAuthorized = umaResources.Any(ua => ua.Permissions.Where(p => p.Scopes.Any(sc => scopes.Contains(sc))) .All(pr => pr.Claims.All(cl => claimTokenFormatFetcherResult.Payload.Any(c => c.Key == cl.Name && !c.Value.ToString().Equals(cl.Value, StringComparison.InvariantCultureIgnoreCase))))); if (isNotAuthorized) { var pendingRequests = await _umaPendingRequestRepository.FindByTicketIdentifier(permissionTicket.Id, cancellationToken); if (pendingRequests.Any()) { return(BuildError(HttpStatusCode.Unauthorized, UMAErrorCodes.REQUEST_DENIED, UMAErrorMessages.REQUEST_DENIED)); } foreach (var umaResource in umaResources) { var permissionTicketRecord = permissionTicket.Records.First(r => r.ResourceId == umaResource.Id); var umaPendingRequest = new UMAPendingRequest(permissionTicket.Id, umaResource.Subject, DateTime.UtcNow) { Requester = claimTokenFormatFetcherResult.Subject, Scopes = umaResource.Scopes, Resource = umaResource }; await _umaPendingRequestRepository.Add(umaPendingRequest, cancellationToken); } await _umaPendingRequestRepository.SaveChanges(cancellationToken); return(new ContentResult { ContentType = "application/json", StatusCode = (int)HttpStatusCode.Unauthorized, Content = new JObject { { "request_submitted", new JObject { { UMATokenRequestParameters.Ticket, permissionTicket.Id }, { "interval", _umaHostOptions.RequestSubmittedInterval } } } }.ToString() }); } var jArr = new JArray(); foreach (var permission in permissionTicket.Records) { jArr.Add(new JObject() { { UMAPermissionNames.ResourceId, permission.ResourceId }, { UMAPermissionNames.ResourceScopes, new JArray(permission.Scopes) } }); } var result = BuildResult(context, scopes); foreach (var tokenBuilder in _tokenBuilders) { await tokenBuilder.Build(scopes, new JObject { { "permissions", jArr } }, context, cancellationToken); } _tokenProfiles.First(t => t.Profile == context.Client.PreferredTokenProfile).Enrich(context); foreach (var kvp in context.Response.Parameters) { result.Add(kvp.Key, kvp.Value); } return(new OkObjectResult(result)); } catch (OAuthException ex) { return(BuildError(HttpStatusCode.BadRequest, ex.Code, ex.Message)); } }