I am not so sure the model of using a central oidc solution as the primary login to your app is such a good idea. There are so many failure points in just getting to and fro the oidc portal that can break in all sorts of ways, with no good way of debugging, leaving users stranded in the middle of redirects. Especially as logs are split between 3 parties, the browser, the client (server) and the oidc server.
I ripped out our oidc primary login and implemented comparable features in my current company (this is probably not for everyone though), it has vastly reduced support tickets, and generally been a faster and more intuitive solution, but more expensive, and requires more domain knowledge. Still I'd rather have that than having a team spend years handling support tickets for endless social login issues.
If you choose to use oidc, please, please only use it for social logins, don't do oidc within oidc within oidc (I am not exaggerating, I've seen 5 levels of nested oidc and oauth2 flows). Like a lot of these solutions such as Zitadel, Auth0, etc. It becomes a nightmare to support and mature.
Before OIDC it we had (mostly) SAML but it is a beast by comparison and was limited to enterprise use.
The ability of being able to switch auth out with another identity provider with such ease has been nothing short of a blessing.
Yes some overuse redirects and do weird things but the social ones I’ve used plus Okta and my own home grown ones have all been fine.
As I mentioned previously using it for social logins by itself, is fine in most situations as they're quite mature. And IMO the best and probably intended use case of the technology and there it works quite well.
Isn't a simple redirect in the same window enough? Redirect to OIDC provider -> login -> redirect back APP -> get OIDC state from URI params?
Especially in an app context it becomes a minefield of half baked webview implementations, browser specific quirks, and limitations on how to call back to the host app which initiated the flow.
Other questions are how do we handle return urls, i.e. return to where we started the login flow from? there isn't a good answer in oidc, unless you use some of the more extreme flows. It becomes tricky to implement without opening yourself to open redirect attacks, which kind of voids the benefits of oidc (that you don't have to handle the complexity of the authentication).
Also there are endless variations of the oidc flow, the most common being code flow, which is pretty much what you describe. But it gets increasingly complex as you have to handle native app login (PKCE pronounced pixie). Using these flows you end up becoming as much an expert in the technology as you would've been just implementing authentication and identity yourself.
You can quickly get to 3 levels if e.g. your app uses auth0, github login is supported and then the user does social login to github etc.
2 or 3 levels of federation is common.
More levels are possible which is bad if you value your sanity but I think (well, hope) rare in practice. The way you get to 4 or 5 levels is if you have organisational dysfunction on top of all this and you are forced to do your logins thru e.g. one or more fed servers owned by a different team in your company (who add even more layers of indirection).
Mostly as a relying party you will be insulated from all the complexity but if you own your oidc server and manage the brokering you will probably have to deal with a lot of edge cases.
I’ve seen it a few time and can only conclude it’s the work of amateurs.
The missed I've seen is simple that oidc was used on multiple levels to facilitate a login flow and the sessions discarded afterwards
Failure galore
However, what becomes problematic is handling inherent complexity of whatever the provider you use is. If the OIDC flow is only intended for you or in-house at a company then it is less problematic. But when used by all sorts of people and devices, it will break in all sorts of problematic ways.
But that isn't to say that you shouldn't use the technology it is fantastic at what it does. I.e. handle social identities in the case of oidc, and authorization in the case of oauth
SetEnv proxy-initial-not-pooled 1
SetEnv proxy-nokeepalive 1
otherwise connections would randomly drop. I was looking for other ways to make development a bit easier and also settled on mod_auth_openidc, which is an Apache module that lets it act like a Relying Party and handle lots of the heavy lifting (protecting endpoints, refreshing tokens etc.) for me, and lets me work with just a few headers that are passed to the protected resources: https://github.com/OpenIDC/mod_auth_openidcIt works, but I'm still not happy - I realize that there are many types of attacks that have historically been a problem and that certain OpenID Connect flows try to protect against, in addition to the fact that if I wrote my own security code it'd almost certainly be worse and have vulnerabilities (in the words of Eoin Woods: "Never invent security technology"), and it's a good thing to follow standards... but the whole thing is such a pain. Both OpenID Connect, Keycloak and configuring mod_auth_openidc.
Right now I'm moving permissions/roles back into the app DB, because I don't want to have to work with the Keycloak REST API every time I want to change what a user can or cannot do in the system, in addition to permissions which might only apply conditionally (one user might be related to multiple organizations, having different permissions in the context of each).
Regardless, it's nice that there are more pieces of software out there to choose from! Do manage your expectations when working with OpenID Connect, though.
Multitenancy is hard, messy and error-prone. Do you really need it, or maybe you could be happy with user-per-tenant scheme?
I come across it less and less. To the point where I get the feeling it's just some legacy implementions that have it, but nothing more.
It has been written with keycloak as the auth server but should work for any proper openid connect implementation since I used the specification as a guide.
This alone sets it apart for us. Lots of other solutions don’t offer this. And then users make requests to our software for this ability and like I tell them, there’s no way our software is going to insert itself into your authentication system. That’s for your authentication system!!
Anyway, I seem to be the minority here but maybe that’s the domain I work in.
Highly encourage everyone jump into source code and explore how IntrospectionResponse struct work with all related code around
https://github.com/zitadel/oidc/blob/main/pkg/oidc/introspec...
// IntrospectionResponse implements RFC 7662, section 2.2 and
// OpenID Connect Core 1.0, section 5.1 (UserInfo).
// https://www.rfc-editor.org/rfc/rfc7662.html#section-2.2.
// https://openid.net/specs/openid-connect-core-1_0.html#Standa....
type IntrospectionResponse struct { Active Scope ClientID TokenType ... exp iat nbf sub Audience ... aud ... JWTID ... Claims map[string]any }
If you want to explore the difference between identity providers, click through
https://github.com/nextauthjs/next-auth/tree/main/packages/c...
Azure is the most insane ... and it's a lot of fun to compare them all against each other.
Next go though PKCE (Proof Key for Code Exchange) and look how code_challenge, code_verifier works or at least see interfaces .
Ory Fosite is a great alternative too https://github.com/ory/fosite
Support PKCE #59835 in x/oauth2 https://github.com/golang/go/issues/59835
Scott Brady's content is great for undetstanding the topic
SPA Identity and Access Control with OpenID Connect https://www.youtube.com/watch?v=rP3St0GU_Bk OAuth is Not Authentication https://www.scottbrady91.com/oauth/oauth-is-not-authenticati...
SPA is a landmine ..
OAuth 2 0 and OpenID Connect for Single Page Applications Philippe De Ryck https://www.youtube.com/watch?v=XoBtUn4XczU
The deeper you go into the topic the more you will discover. It's an ultimate "rabbit hole" - web, native, SPA flows, PKCE, JWT, session storage, custome middleware for your favorite flavor of backend framework, etc