Skip to content
This repository has been archived by the owner on Sep 18, 2021. It is now read-only.

Authorize in MVC controllers #1148

Closed
oliveiracdz opened this issue Apr 6, 2015 · 10 comments
Closed

Authorize in MVC controllers #1148

oliveiracdz opened this issue Apr 6, 2015 · 10 comments

Comments

@oliveiracdz
Copy link

Hi everyone,

In the CustomUserService sample e.g., it's possible to protect a MVC controller with katana openId middleware pointing to Identity Server itself?
I've tried, but the protected controllers doesn't redirect to login. Instead, it responds 401 - Unauthorized.

Thanks!

@brockallen
Copy link
Member

Yes -- I can post a sample of this.

@oliveiracdz
Copy link
Author

Hi Brock,

I think this might be a bug.
To reproduce, it's just decorate LocalRegistrationController with the AuthorizeAttribute and add a UseCookieAuthentication pointing to a ordinary login page. The Katana doesn't redirect to login page, showing only a 401 error.
But if I remove UseIdentityServer from the OWIN, the redirect occurs normally.
Can I'm missing something?

Thanks again!

@brockallen
Copy link
Member

I guess my comment above was making an assumption that I'm not sure of anymore. It sounded like you wanted a registration controller that sat next to IdentityServer in the same host, much like you would for a controller that's the target of a partial login. Is that what you're looking for?

@oliveiracdz
Copy link
Author

Actually, I'm using all ASP.NET Identity controllers sat next to IdentityServer in the same host.
In the account management controller e.g., the user need be authenticated or redirected to the login page.
But it only shows the 401 page error. =/

Sorry for the poor English. =P
Became clearer now?

@brockallen
Copy link
Member

If your MVC code sits next to IdSvr and you want it to be your "login page" then I can post some sample code (when I get some time). Otherwise you need to move your MVC code out of IdSvr and use normal OIDC to authenticate.

@oliveiracdz
Copy link
Author

Hi Brock,

I just want to protect some resources sited next to IdSvr, just like you do with the "application permissions" page. See my screens please:

img01

img2

Thank you!

@brockallen
Copy link
Member

The issue is that our login page requires a protocol to use it. You'll need something like this:

public abstract class OwinAuthenticationAttribute : FilterAttribute, IAuthenticationFilter
    {
        public string AuthenticationType { get; set; }

        protected OwinAuthenticationAttribute(string authenticationType)
        {
            if (String.IsNullOrWhiteSpace(authenticationType)) throw new ArgumentNullException("authenticationType");

            AuthenticationType = authenticationType;
        }

        public virtual void OnAuthentication(AuthenticationContext filterContext)
        {
            var ctx = filterContext.HttpContext.Request.GetOwinContext();
            var result = AsyncHelper.RunSync(() => ctx.Authentication.AuthenticateAsync(AuthenticationType));
            if (result != null && 
                result.Identity != null && 
                result.Identity.IsAuthenticated)
            {
                filterContext.Principal= new ClaimsPrincipal(result.Identity);
            }
        }

        public abstract void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);
    }

    public class IdentityServerFullLoginAttribute : OwinAuthenticationAttribute
    {
        public IdentityServerFullLoginAttribute()
            : base(Constants.PrimaryAuthenticationType)
        {
        }

        public override void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
        {
            var statusCodeResult = filterContext.Result as HttpStatusCodeResult;
            if (statusCodeResult != null && statusCodeResult.StatusCode == 401)
            {
                var ctx = filterContext.HttpContext.Request.GetOwinContext();
                var url = ctx.Environment.CreateSignInRequest(new Thinktecture.IdentityServer.Core.Models.SignInMessage
                {
                    ReturnUrl = filterContext.HttpContext.Request.Url.AbsoluteUri
                });
                filterContext.Result = new RedirectResult(url);
            }
        }
    }

@johnkors
Copy link
Contributor

johnkors commented Apr 9, 2015

Or if you don't need access to the idsrv bits in your part of the application (outside idsrv), you can use the Map method of Katana like in the samples, and use the OIDC middleware for the other path (your client) to connect to idsrv like you would with any other client.

app.Map("/core" a => a.UseIdsrv())
app.Map("/myapp", a => a.UseOpenIdConnectMw())  

@oliveiracdz
Copy link
Author

John, thanks! Yes, I need the "bits of IdSrv" in my part of application and I was trying to use the OIDC middleware. That was my fail.

Brock, the snipet is exactly what I was looking for!
I've only made some adjusts in the resulting identity object and I've added the filter as global.
Now I can use all features of MVC Web Application template (with AspNet.Identity) and the IdentityServer as well.
It's amazing! Thank you so much!

Cheers from Brazil! o/

@buybackoff
Copy link

Spent several hours on this and finally the additional attribute above by @brockallen made it work (needed to add core prefix to url). I use standard MVC5 template and added IdSrv to it as app.Map("/core" a => a.UseIdsrv()). Still cannot understand why MVC Authentication sample works smoothly? I am using EF+AspIdentity (combined pieces from examples). Why this affects redirection? A separate MVC app with exactly the same code works well.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants