FunctionMonkey icon indicating copy to clipboard operation
FunctionMonkey copied to clipboard

Http Trigger: AuthorizationLevel.Anonymous runs ClaimsPrincipalAuthorization but it should be ignored

Open alexeymarkov opened this issue 5 years ago • 3 comments

ClaimsPrincipalAuthorization requires ClaimsPrincipal which is not resolved for AuthorizationLevel.Anonymous. As a consequence ClaimsPrincipal null is passed to ClaimsPrincipalAuthorization:

Change `

    {{#if ValidatesToken}}
        if (req.Headers["{{TokenHeader}}"].Count == 0)
        {
            return new UnauthorizedResult();
        }
        string authorizationHeader = req.Headers["{{TokenHeader}}"][0];
        if (string.IsNullOrWhiteSpace(authorizationHeader))
        {
            return new UnauthorizedResult();
        }
        
        principal = await pluginFunctions.ValidateToken(authorizationHeader);
        if (principal == null)
        {
            return new UnauthorizedResult();
        }
        contextSetter.SetHttpContext(principal, requestUrl, headerDictionary);    
    {{/if}}

    {{#if AuthorizesClaims}}
        var claimsPrincipalAuthorizationResult = await pluginFunctions.IsAuthorized(principal, req.Method, requestUrl);
        if (!claimsPrincipalAuthorizationResult)
        {
            return new UnauthorizedResult();
        }
    {{/if}}

`

to `

    {{#if ValidatesToken}}
        if (req.Headers["{{TokenHeader}}"].Count == 0)
        {
            return new UnauthorizedResult();
        }
        string authorizationHeader = req.Headers["{{TokenHeader}}"][0];
        if (string.IsNullOrWhiteSpace(authorizationHeader))
        {
            return new UnauthorizedResult();
        }
        
        principal = await pluginFunctions.ValidateToken(authorizationHeader);
        if (principal == null)
        {
            return new UnauthorizedResult();
        }
        contextSetter.SetHttpContext(principal, requestUrl, headerDictionary);

        {{#if AuthorizesClaims}}
            var claimsPrincipalAuthorizationResult = await pluginFunctions.IsAuthorized(principal, req.Method, requestUrl);
            if (!claimsPrincipalAuthorizationResult)
            {
                return new UnauthorizedResult();
            }
        {{/if}}
    {{/if}}

`

alexeymarkov avatar Jun 10 '20 07:06 alexeymarkov

Does this mean that after this change anonymous endpoints will skip ClaimsPrincipalAuthorizationDefault? If so looking forward to this change.

Current behavior doesn't seem right. Why would anonymous endpoint be checked in ClaimsPrincipalAuthorizationDefault? This is causing issues if you set up some custom data (like user context) in TokenValidator and afterwards check it in ClaimsPrincipalAuthorizationDefault.

jlocans avatar Oct 01 '20 13:10 jlocans

Yes, this will be ignore. Alternatively you can also use a custom IClaimsPrincipalAuthorization implementation and apply it to anonymous endpoints public class AllowAnonymousClaimsAuthorization : IClaimsPrincipalAuthorization { public Task<bool> IsAuthorized(ClaimsPrincipal claimsPrincipal, string httpVerb, string url) { return Task.FromResult(true); } }

alexeymarkov avatar Oct 01 '20 13:10 alexeymarkov

@alexeymarkov Thanks for the tip. Works great!

jlocans avatar Oct 08 '20 12:10 jlocans