示例#1
0
        /// <summary>
        /// Used in web APIs (no user interaction).
        /// Replies to the client through the HTTP response by sending a 403 (forbidden) and populating the 'WWW-Authenticate' header so that
        /// the client, in turn, can trigger a user interaction so that the user consents to more scopes.
        /// </summary>
        /// <param name="scopes">Scopes to consent to.</param>
        /// <param name="msalServiceException">The <see cref="MsalUiRequiredException"/> that triggered the challenge.</param>
        /// <param name="httpResponse">The <see cref="HttpResponse"/> to update.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public async Task ReplyForbiddenWithWwwAuthenticateHeaderAsync(IEnumerable <string> scopes, MsalUiRequiredException msalServiceException, HttpResponse httpResponse, string additional_info = null)
        {
            // A user interaction is required, but we are in a web API, and therefore, we need to report back to the client through a 'WWW-Authenticate' header https://tools.ietf.org/html/rfc6750#section-3.1

            try
            {
                // Create response header as per https://tools.ietf.org/html/rfc6750#section-3.1
                string parameterString = CommonUtil.CreateResponseHeader(AuthenticationConfig, msalServiceException.Claims, scopes);

                var headers = httpResponse.Headers;

                httpResponse.StatusCode = (int)HttpStatusCode.Forbidden;

                headers[HeaderNames.WWWAuthenticate] = new StringValues($"Bearer {parameterString}");

                string message = msalServiceException.Message;

                // Create response content with error details.

                InsufficientClaimsResponse insufficientClaimsResponse = CommonUtil.CreateErrorResponseMessage(message, additional_info);
                httpResponse.Write(Newtonsoft.Json.JsonConvert.SerializeObject(insufficientClaimsResponse));
            }
            catch (Exception ex)
            {
                var a = ex.Message;
            }
        }
示例#2
0
        /// <summary>
        /// Checks if the access token has acrs claim with acrsValue.
        /// If does not exists then adds WWW-Authenticate and throws UnauthorizedAccessException exception.
        /// </summary>
        /// <param name="acrsValue"></param>
        /// <param name="httpResponse"></param>
        public static void EnsureUserHasAuthenticationContextClassReference(string acrsValue, string additionalInfo = null)
        {
            AuthenticationConfig authenticationConfig = new AuthenticationConfig();

            HttpContext context = HttpContext.Current;

            ClaimsPrincipal claimsPrincipal = ClaimsPrincipal.Current;

            string authenticationContextClassReferencesClaim = "acrs";

            if (context == null || context.User == null || claimsPrincipal.Claims == null || !claimsPrincipal.Claims.Any())
            {
                throw new ArgumentNullException("No Usercontext is available to pick claims from");
            }

            Claim acrsClaim = claimsPrincipal.FindFirst(authenticationContextClassReferencesClaim);

            if (acrsClaim == null || acrsClaim.Value != acrsValue)
            {
                context.Response.StatusCode = (int)HttpStatusCode.Forbidden;

                //string message = string.Format(CultureInfo.InvariantCulture, "The presented access tokens had insufficient claims. Please request for claims requested in the WWW-Authentication header and try again.");
                var base64str = Convert.ToBase64String(Encoding.UTF8.GetBytes("{\"access_token\":{\"acrs\":{\"essential\":true,\"value\":\"" + acrsValue + "\"}}}"));

                // Create response header as per https://tools.ietf.org/html/rfc6750#section-3.1
                var authenticateHeader = CommonUtil.CreateResponseHeader(authenticationConfig, base64str);

                context.Response.Headers.Add("WWW-Authenticate", authenticateHeader);


                string message = $"The claim 'acrs' is either missing or does not have the value(s) '{acrsValue}'.Please redirect the user to the authorization server for additional processing.";

                // Create response content with error details.
                InsufficientClaimsResponse insufficientClaimsResponse = CommonUtil.CreateErrorResponseMessage(message, additionalInfo);
                if (insufficientClaimsResponse != null)
                {
                    context.Response.Write(Newtonsoft.Json.JsonConvert.SerializeObject(insufficientClaimsResponse));
                }

                context.Response.End();

                throw new UnauthorizedAccessException(message);
            }
        }
        /// <summary>
        /// Create Response Content for insufficient claims.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="addionalInfo"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        internal static InsufficientClaimsResponse CreateErrorResponseMessage(string message, string addionalInfo = null, string requestId = null)
        {
            InsufficientClaimsResponse insufficientClaimsResponse = new InsufficientClaimsResponse();

            insufficientClaimsResponse.Code           = Constants.InsufficientClaims;
            insufficientClaimsResponse.Message        = message;
            insufficientClaimsResponse.AdditionalInfo = addionalInfo;

            insufficientClaimsResponse.InnerError = new ResponseInnerError();

            insufficientClaimsResponse.InnerError.Date = DateTime.UtcNow;

            if (requestId == null)
            {
                requestId = Guid.NewGuid().ToString();
            }
            insufficientClaimsResponse.InnerError.RequestId       = requestId;
            insufficientClaimsResponse.InnerError.ClientRequestId = requestId;
            return(insufficientClaimsResponse);
        }