MV10 / mv10.github.io

McGuireV10's personal blog
MIT License
4 stars 2 forks source link

Blazor Authentication with OpenID Connect - Forty Years of Code #53

Open utterances-bot opened 4 years ago

utterances-bot commented 4 years ago

Blazor Authentication with OpenID Connect - Forty Years of Code

Blazor OIDC login, logout, and anonymous access with IdentityServer

https://mcguirev10.com/2019/12/15/blazor-authentication-with-openid-connect.html

HuntJason commented 4 years ago

Am I correct in assuming that where you state "_Hub.cshtml" you are meaning "_Host.cshtml"? I don't find a "_Hub.cshtml" file in the default template.

MV10 commented 4 years ago

Seems likely :)

psychomonkey911 commented 4 years ago

after start progect my app redirect to https://MyIdentityServer/home/error?errorId=CfDJ8KcpGmbsq5... and i see Sorry, there was an error : unauthorized_client Request Id: 8001a1a8-0800-da00-b63f-84710c7967bb I think the error in identity server settings in [Identity].[dbo].[ClientRedirectUris] i put uri like https://localhost:44305/authentication/login-callback in [Identity].[dbo].[ClientCorsOrigins] i put origin same url https://localhost:44305

can you help me with setup identity?!

MylesRip commented 4 years ago

I tried moving the ClientSite to Docker, no problem. Then I tried setting up my own IS4 server running in a separate container (instead of using the IS4 demo site), but get an error saying that "the remote certificate is invalid according to the validation procedure". After weeks of trying many things, I still can't get this to work with my own IS4 server in a development environment. I wondering if you had better success in your further adventures into this kind of scenario.

MylesRip commented 4 years ago

P.S. I probably should've mentioned that I'm wanting to use TLS for communicating between the containers on the backend.

MV10 commented 4 years ago

Hi @MylesRip -- unfortunately I haven't been working with IdentityServer4 lately. The Powers That Be at my company were wined and dined by the PingIdentity sales people (and in all fairness, the larger corporate entity had already standardized on that product) so our local IDS4 plans went out the window -- even though everyone in our division feels it's a better system. So goes life at BigCorp.

All that being said, a couple years ago I wrote an article about IdentityServer certificate usage, maybe you can find something helpful there? I think that error is probably from IDS4 token validation certs. Article here. Shortly after writing this Blazor article, I had IDS4 chugging along just fine on Azure with a Blazor Server app hitting it for awhile and didn't have cert issues. I also (unfortunately) haven't had any need or time to play around with containers yet so I can't even guess how that might change things.

Sorry, wish I could be of more help.

MylesRip commented 4 years ago

Hi @MV10 , Thanks for your quick response. I've been focusing on SSL certs (even creating my own custom root CA) and wasn't even thinking about IDS4 token certs. I'll check out the article you mentioned and see if that helps me to get past this point. I really appreciate your original article above, by the way. Very helpful!

jonasarcangel commented 3 years ago

The code doesn't work for me. It is getting redirected to localhost instead of my public server URL.

https://github.com/dotnet/aspnetcore/issues/26757

MarkClouden commented 3 years ago

It seems strange still to AddMvcCore just so that auth policy services are used, but I have resigned myself to it. FYI, you can still use AddAuthorization and establish your policies through its AuthorizationOptions callback parameter.

In that way you can decorate pages with @attribute [Authorize] and only those pages will look to enforce the policy (default or other). I find that simpler than having a global filter. Preference, entirely, of course - just pointing it out.

services.AddMvcCore();
services.AddAuthorization(o => {
o.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

Also, whenever I hear of docker container->container https issues, i almost immediately assume: trusted root CA. A self-signed cert at A cannot be validated by client at B. It just doesnt work. I would suggest a formal cert, but even then you must ensure the trusted root CA is available to the container B (windows - trusted root store, linux - something on image filesystem, i forget just now where/how).

For test purposes, I routinely will use (assuming you control the httpclient code, or have an option to provide a httpclienthandler, is to provide a ServerCertificateCustomValidationCallback which just returns true (performs no cert validation) (to be used only in PoC level code, never beyond that). You client will no longer care about the server cert and always accepts it as valid - removing the need to mess about with getting your self-signed server cert accepted.

Thanks for the original write-up. I was already there, but its always good to find independent confirmation of what I had coded.

MV10 commented 3 years ago

It seems strange still to AddMvcCore just so that auth policy services are used, but I have resigned myself to it.

When I wrote this, I hadn't found documentation about exactly what AddMvcCore really adds -- but either I had overlooked it (and hadn't thought to check their source) or MS has documented it now, and it's just a convenience function, everything it does could be added individually.

I'm not really keeping this up to date though. Unfortunately an anti-MS Java type at our company has final say-so on various tech stacks and has brought down the ban-hammer on Blazor, so as far as UI at the day job goes, I'm back to half-assed plague-of-libraries JS-framework stacks until I retire.

MarkClouden commented 3 years ago

Feel ya there. My current work is a PoC, but in the end we will select Vue. But I will continue just so I have it on record the benefits (single front-end/back-end language specialization, solid unit test-ability/tooling, and so on).

alwilton commented 3 years ago

Extremely valuable article. I did find one improvement to be made. In the HostAuthModel change the code to

    public IActionResult OnGetLogin(string returnUrl = null)
    {
        returnUrl ??= Url.Content("~/");
        return Challenge(AuthProps(returnUrl), "oidc");
    }

    private AuthenticationProperties AuthProps(string returnUrl = null)
        => new AuthenticationProperties
        {
            RedirectUri = returnUrl // Url.Content("~/")
        };

Now when an @attribute [Authorize] page is hit you will can be redirected back to the page after login.

danielheddelin commented 3 years ago

Great articles Jon, they have been very helpful. One thought: Should not the in app.razor be between and instead of within NotFound? And secondly, I also enounter this problem "The login identity was gone" - after some idle time (intermettent), when hitting OnGet() in _HostAuth, there is no Identity and no Claims, and therefore IsAuthorized is false. Have you managed to solve this? It is driving me crazy.

danielheddelin commented 3 years ago

"Should not the CascadingAuthenticationState in app.razor be between StateProvider and Router instead of within NotFound?"

MV10 commented 3 years ago

@danielheddelin It may have changed, when I wrote those articles, a lot of Blazor was still very much in flux -- or I may have gotten it wrong. I'm sad to say I haven't worked with it since I wrote the last of these articles. Unfortunately a senior manager (anti-MS Java guy) banned it in our part of the company and we had to toss a year of work and start over with crappy JS-based UI. Oh well, they keep paying me, right?

skba commented 3 years ago

Hi Jon, this might be a little off topic. I have been working on a blazor server app that authenticates with IdentityServer4. It calls API for app based logic. Upon authentication, access token received from identity server works fine. However, i would like to add additional claims to the token and these additional claims have to come from the app data store, NOT from IdentityServer data store. I implemented IPostConfigureOptions interface and "OnTicketReceived" event, i call API to fetch additional claims from app data store and attached it them to the Principal and registered this server. However, this did not work while making an API call and sending access token as bearer to api. I was wondering if you have any thoughts on this ?

ll1325 commented 2 years ago

I am new to Blazor. When I follow these steps, I get stuck on Configure OIDC in Startup. "services" does not exist in this context. Do you have a sample project code available?

MV10 commented 2 years ago

@ll1325 The sample code is linked at the start of the article:

https://github.com/MV10/BlazorOIDC

However, this is pretty old, I'm not keeping it up to date, I would almost guarantee it's unlikely to work under current Blazor and IdentityServer releases. Blazor and .NET Core changes very quickly! Hopefully some of the basic concepts may still be useful though.

robnelder commented 2 years ago

After spending a lot of time working on the stale cookies issue, I think we have a solution that works and is relatively principled. I've documented our solution as a stackoverflow Q&A. Please have a look here: https://stackoverflow.com/questions/72868249

I would welcome constructive feedback or recommendations for any significant improvements. Some upvotes would be nice too :)