Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AuthorizationHandlerContext.Resource is not of type Endpoint with Endpoint Routing #13572

Closed
jessicah opened this issue Aug 30, 2019 · 9 comments
Labels
area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates
Milestone

Comments

@jessicah
Copy link

According to #11705, AuthorizationHandlerContext.Resource should be an instance of Endpoint in ASP.NET Core 3.0 when using endpoint routing, but it is instead an instance of my resource. Perhaps this is because I'm using the AuthorizationHandler<TRequirement, TResource> version, but from documentation I've read, that seems to be the right thing to do, and indeed has worked correctly thus far. However, I now want to redirect to a different error page when authorization fails, but I cannot fetch Endpoint as documented in linked issue.

public class EmailAuthorizationHandler : AuthorizationHandler<SameEmailRequirement, Models.Member>
{
	protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SameEmailRequirement requirement, Models.Member resource)
	{
		if (context.User.HasClaim(claim => claim.Type == ClaimTypes.Email))
		{
			var emailAddress = context.User.Claims.SingleOrDefault(claim => claim.Type == ClaimTypes.Email)?.Value;

			if (emailAddress != null && 
				(emailAddress.ToLowerInvariant() == resource.EmailAddress?.ToLowerInvariant() ||
				emailAddress.ToLowerInvariant() == resource.ZwiftEmailAddress?.ToLowerInvariant()))
			{
				context.Succeed(requirement);
			} else
			{
				if (context.Resource is Endpoint endpoint)
				{
					// False
				}
				if (context.Resource is Models.Member resourceIsMember)
				{
					// True
				}
			}
		}

		return Task.CompletedTask;
	}
}

public class SameEmailRequirement : IAuthorizationRequirement { }
@mkArtakMSFT mkArtakMSFT added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer and removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels Aug 30, 2019
@blowdart blowdart added the area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates label Aug 30, 2019
@blowdart
Copy link
Contributor

The linked issue isn't an authorization issue.

What is calling into your handler? Are you doing it declaratively with the attribute or imperatively with code?

@mkArtakMSFT mkArtakMSFT added the Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. label Sep 3, 2019
@mkArtakMSFT
Copy link
Member

Hi. We're closing this issue as we have heard no response from you for some time now. If you have more details and are encountering this issue please add a new reply and re-open the issue.

@jessicah
Copy link
Author

jessicah commented Sep 5, 2019

Sorry, typo, I meant #11075, and didn't see the email notification :/

services.AddAuthorization(options =>
{
	options.AddPolicy("SameEmail", policy => policy.Requirements.Add(new SameEmailRequirement()));
});

services.AddSingleton<IAuthorizationHandler, EmailAuthorizationHandler>();
			

@mkArtakMSFT mkArtakMSFT reopened this Sep 6, 2019
@mkArtakMSFT
Copy link
Member

/cc @blowdart

@blowdart
Copy link
Contributor

blowdart commented Sep 6, 2019

@HaoK is this expected for endpoint routing?

@blowdart blowdart removed the Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. label Sep 6, 2019
@HaoK
Copy link
Member

HaoK commented Sep 12, 2019

As mentioned in the original post, using AuthorizationHandler<SameEmailRequirement, Models.Member> will explicitly prevent HandleRequirementAsync from getting called unless the resource matches, you shouldn't use this base class if you want to see more than the resource you specify.

https://github.com/aspnet/AspNetCore/blob/master/src/Security/Authorization/Core/src/AuthorizationHandler.cs#L49

        public virtual async Task HandleAsync(AuthorizationHandlerContext context)
        {
            if (context.Resource is TResource)
            {
                foreach (var req in context.Requirements.OfType<TRequirement>())
                {
                    await HandleRequirementAsync(context, req, (TResource)context.Resource);
                }
            }
        }

@HaoK HaoK added this to the Discussions milestone Sep 12, 2019
@HaoK HaoK removed their assignment Sep 12, 2019
@jessicah
Copy link
Author

So how do I write an AuthorizationHandler that has access to both the Endpoint instance and the Models.Member instance?

I'd like to do something like https://www.reddit.com/r/dotnet/comments/9vc6ym/custom_redirect_for_authorization_policy_failure/ to customize the route dictionary to go to particular pages.

From what I can see, that doesn't seem to be possible? I need both Endpoint and Models.Member available. I haven't been able to find any example of how this is supposed to be achieved.

@analogrelay
Copy link
Contributor

So how do I write an AuthorizationHandler that has access to both the Endpoint instance and the Models.Member instance?

If you're explicitly authorizing against a custom resource like Models.Member then that's the resource you'll get in the handler. If you need access to other data (like the Endpoint), you'll need to add that to the resource you provide when authorizing. You should be able to access it off the HttpContext when you create your resource. For exmaple:

var endpoint = // Get Endpoint off HttpContext (I don't remember off-hand exactly where it is)
var member = // your code to get the Models.Member object
authzService.AuthorizeAsync(...., new MyCustomResource(member, endpoint));

@ghost
Copy link

ghost commented Dec 2, 2020

Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.

This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!

@ghost ghost closed this as completed Dec 2, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Jan 1, 2021
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-auth Includes: Authn, Authz, OAuth, OIDC, Bearer area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates
Projects
None yet
Development

No branches or pull requests

6 participants