Beispiel #1
0
        /// <copydoc cref="IActivityAuthorizer.IsAuthorizedAsync" />
        public async Task <AuthorizationReason> IsAuthorizedAsync(string resource, string action, IPrincipal principal, IDictionary <string, object> values = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var scope = await scopeProvider.AuthorizationScopeAsync(cancellationToken).ConfigureAwait(false);

            if (scope == null)
            {
                Logger.Warn("No data returned from scope provider");
                scope = new AuthorizationScope {
                    Name = "Default"
                };
            }

            var activities = scope.Activities.ToDictionary();

            // Get the state for this request
            var defaultAuthorization        = scope.DefaultAuthorization ?? DefaultAuthorization;
            var defaultActivity             = scope.DefaultActivity ?? DefaultActivity;
            var defaultAllowUnauthenticated = scope.AllowUnauthenticated ?? DefaultAllowUnauthenticated;

            // Set up the reason
            var reason = new AuthorizationReason
            {
                Resource  = resource,
                Action    = action,
                Principal = principal,
                // We will always make a decision at this level
                NoDecision   = false,
                IsAuthorized = defaultAuthorization
            };

            // Do a short-circuit check for the unauthenticated state, will be overridden if there is a matching activity
            if (!defaultAllowUnauthenticated && !principal.Identity.IsAuthenticated)
            {
                reason.IsAuthorized = false;
                reason.Reason       = "IsAuthenticated: false";
            }

            // Check the activities
            foreach (var activity in activities.FindActivities(resource, action, defaultActivity))
            {
                var rs = principal.IsAuthorized(activity, defaultAuthorization);
                if (rs.NoDecision)
                {
                    // Try the next one
                    continue;
                }

                // Ok, we have a decision
                reason.IsAuthorized = rs.IsAuthorized;
                reason.Identity     = rs.Identity;

                if (reason.Resource != rs.Resource || reason.Action != rs.Action)
                {
                    // Decided based on some other activity, so say what that was
                    reason.PrincipalReason = rs;
                }
                else
                {
                    // Preserve the reason information
                    reason.Reason = rs.Reason;
                }

                // We are done as we have a decision
                break;
            }

            if (!reason.IsAuthorized)
            {
                Logger.InfoFormat("Failed authorization: User '{0}', Resource: '{1}', Action: '{2}'", principal == null ? "<Unknown>" : principal.Identity.Name, resource, action);
            }

            return(reason);
        }
 public async Task <AuthorizationScope> AuthorizationScopeAsync(CancellationToken cancellationToken = default(CancellationToken))
 {
     // TODO: With this design we can only cache one provider which might be issue with multiple microservices.
     // Might need the provider to have a name property so we can record it against that
     return(await AddOrGetExistingAsync("activities", async() => await provider.AuthorizationScopeAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false));
 }