
Understanding OAuth2 and OpenID Connect - bswamina
https://www.polarsparc.com/xhtml/OAuth2-OIDC.html
======
mooreds
This was a good article. The first section, explaining the reason why OAuth2
is a fit for certain data flow needs, was really strong. I liked the diagram
of the flow as that made it clear what all the pieces were.

I think that if you need that separation between your resource servers and
authorization server, the OAuth dance can be a bit complicated, you can just
use a simple api key. But as soon as you start to allow outside access to your
systems, I'd suggest using an OAuth server (disclosure, I work for FusionAuth,
a free as in beer competitor to Keycloak, Gluu, etc).

Additional things that I wish had been in the article:

* Don't use implicit flow, use the authorization code grant with PKCE.

* Don't use resource owner password flow; it was designed to allow existing systems to bridge into OAuth and shouldn't be used in new systems today.

Both the implicit flow and the resource owner password flow are not part of
OAuth 2.1--here's a post I wrote about it:
[https://fusionauth.io/blog/2020/04/15/whats-new-in-
oauth-2-1](https://fusionauth.io/blog/2020/04/15/whats-new-in-oauth-2-1)

* Also, storing access tokens should be done carefully in the browser (httponly, secure cookies is the best way). If you can't do that, then use a server side proxy to store the access tokens. Otherwise your access tokens might get stolen by code executing in the browser.

* OIDC is built on top of OAuth and has a standard set of claims. If you can get by on what OIDC defines, you can switch between identity provider implementations fairly easily.

~~~
different_sort
Storing tokens in cookies would be against the spec wouldn’t it? I’m not
putting rfc6749 on some sort of pedestal, but it clearly states that the
tokens are in the response body and not set in cookies.

Do you have any examples of Authorization servers in the wild doing this or
front end SDKs that work with that?

I’m very curious, I’m doing an SPA security research project at work and I’m
very interested in these stories and learning more.

I’ve seen some folks do refresh in an httponly cookie, and Access in the js
space. I’ve seen another example (auth0) put the refresh token in a web worker
and access token accessible in js.

And I’ve seen things like msal.js just say F it and make them all accessible
to js.

~~~
mooreds
Hiya,

Sorry, I was wrong. According to the spec you definitely have to send the
access token back in the response body[0].

However, a client can store them as cookies (or, as you mention, other places,
such as a service worker[1]). This is useful if the client is a single page
application (SPA), which may need to present the access token to other
resource servers.

RFC 6750 has something to say about how to store the bearer token [2]:

> Don't store bearer tokens in cookies: Implementations MUST NOT store bearer
> tokens within cookies that can be sent in the clear (which is the default
> transmission mode for cookies). Implementations that do store bearer tokens
> in cookies MUST take precautions against cross-site request forgery.

So, I apologize. The authorization server wouldn't send the access token as a
cookie. Instead, there'd be a server side proxy which would request the token
and then send it down as a secure cookie. Again, best practice would be to
keep the access token on the server side proxy and just send a session id down
to the client, but that sometimes doesn't work. Here is a diagram illustrating
that path (with the 'store' entity acting as the proxy mentioned above)[3].

0:
[https://tools.ietf.org/html/rfc6749#section-5.1](https://tools.ietf.org/html/rfc6749#section-5.1)

1:
[https://gitlab.com/jimdigriz/oauth2-worker](https://gitlab.com/jimdigriz/oauth2-worker)

2:
[https://tools.ietf.org/html/rfc6750#page-13](https://tools.ietf.org/html/rfc6750#page-13)

3: [https://fusionauth.io/learn/expert-
advice/authentication/web...](https://fusionauth.io/learn/expert-
advice/authentication/webapp/oauth-authorization-code-grant-jwts-refresh-
tokens-cookies)

~~~
different_sort
Thank you for your replies and insight, it's really appreciated.

The way I see it with SPA and tokens in JS accessible space is that you're
exposing your users to the possibility of token theft and user impersonation
if someone is able pull off an XSS. This is not so different than using a
session cookie that is not marked as 'httponly'. What's old is new again :)

I have also heard the argument that we shouldn't worry about token theft,
because it's already too late if you're XSS'd, but I don't buy into that
rhetoric(not saying XSS isn't incredibly bad).

Unfortunately I work in financial services, so we can't just skate by and
assume that we're so uninteresting that an adversary with advanced
capabilities wouldn't look to exploit our external or internal users somehow.

One another thing we're looking into is access tokens, like having the user
re-authenticate or use a stronger factor(or multiple) to get the AS to grant
them a very short lived, non-refreshable token to do their sensitive
operation.

I'm going to check out the fusionauth blog for a bit more inspiration, if
you're interested in continuing this discussion I would be interested in
carrying it on.

~~~
mooreds
> This is not so different than using a session cookie that is not marked as
> 'httponly'.

The difference is a session cookie is tied to one server, but an access token
could be used with many different APIs or other services. That said, an access
token may expire more quickly, so the devil is definitely in the details.

> One another thing we're looking into is access tokens, like having the user
> re-authenticate or use a stronger factor(or multiple) to get the AS to grant
> them a very short lived, non-refreshable token to do their sensitive
> operation.

That makes sense, for sure. You could definitely require MFA to get an access
token and have it be short lived. At that point it gets to a question of UX
and how much impact you want on your users, but I'm not familiar with all the
requirements you have.

> I'm going to check out the fusionauth blog for a bit more inspiration, if
> you're interested in continuing this discussion I would be interested in
> carrying it on.

Please do! Happy to respond here or if you want to check out the FusionAuth
forum (which I monitor), you can find it on the the website under the
resources tab.

------
taosx
I have wasted so much time on oAuth2 and OIDC the past month that I'm building
a SaaS around it. (not wasted but took away time from the business)

I would have really liked to use auth0 or other authn services but not a fan
of lock-in platforms, I want to export my db without enterprise plans.

The pricing model I'm thinking of is a pay per usage + a commission of the
total usage per month.

Thank you @sjroot

~~~
gurch101
Have you looked at Keycloak like the article suggests? Always thought a SaaS
around keycloak would be a good idea.

~~~
taosx
Even through Keycloak is more mature than ORY ecosystem I went with the latter
as I have more experience with Go than Java. I'm only writing integration,
dashboard. When those thing are ready I'm going to open source and offer a
free option until I add billing, at that point you can either go on-premise or
just continue with us.

Ory will probably offer a cloud service in the near future but I'm just
scratching an itch for now.

------
hardwaresofton
For those who are looking for an alternative and are OK with _centralization_
of Auth which is somewhat different from the goals of OAuth, check out the CAS
standard -- it's an alternative to SAML more so than OAuth.

It's so simple I wrote (and abandoned) a golang library that implements v1[2].
I didn't need the proxy abilities in v2 (and doubt most orgs actually do) and
I use JSON in some places before it was in the standard but it was very easy
to implement and thus I can say it's easy to understand. I've meant to convert
the project to Rust for a long time but at this point I'll probably never get
to it.

[0]: [https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-
Spe...](https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol-
Specification.html)

[1]: [https://apereo.github.io/cas/4.2.x/protocol/CAS-
Protocol.htm...](https://apereo.github.io/cas/4.2.x/protocol/CAS-
Protocol.html)

[2]: [https://github.com/t3hmrman/casgo](https://github.com/t3hmrman/casgo)

~~~
user5994461
I really wouldn't advise to use CAS in 2020. It's an historical curiosity that
stopped being relevant some years ago.

It's an old protocol to do single sign on within a company. It worked well and
I've seen it used in large companies circa 2010, allowing to support sso in
their internal web applications, for employees.

CAS is irrelevant now. The world has standardized on OpenID Connect (and SAML
as second choice). Anything that's on CAS was migrated or is pending migration
to OIDC.

As a developer you will have to deal with OIDC (and maybe SAML) for
integrations with google auth, facebook auth, microsoft active directory. You
really don't want to go for a dying ecosystem (CAS), that's a dead end for
your career.

------
sjroot
Are you implementing OAuth 2 or interested in learning more? I would _highly_
recommend combing through the OAuth 2.1 spec [1] as it incorporates the “best
practices” that were added to 2.0 through additional RFCs.

[1] [https://tools.ietf.org/html/draft-ietf-
oauth-v2-1-00](https://tools.ietf.org/html/draft-ietf-oauth-v2-1-00)

~~~
heliodor
And here's a decent intro that de-mystifies things for those who feel very
confused: [https://youtu.be/996OiexHze0](https://youtu.be/996OiexHze0)

------
candiddevmike
May be worth mentioning--JWTs are not part of the OAuth. They're certainly
used together quite a bit, but you can absolutely use regular session tokens
too.

I say this as someone who thought JWT was a core part of OAuth and it only
added to the perceived complexity of the implementation.

~~~
deathanatos
> _May be worth mentioning--JWTs are not part of the OAuth /OIDC standard._

JWTs _are_ a part of the OIDC standard; from the standard itself[1],

> _The primary extension that OpenID Connect makes to OAuth 2.0 to enable End-
> Users to be Authenticated is the ID Token data structure. The ID Token is a
> security token that contains Claims about the Authentication of an End-User
> by an Authorization Server when using a Client, and potentially other
> requested Claims. The ID Token is represented as a JSON Web Token (JWT)
> [JWT]._

But your comment sounds like you're conflating OAuth & OIDC. (It is true for
_OAuth_ that you're not required to use JWTs.)

[1]: [https://openid.net/specs/openid-connect-
core-1_0.html#IDToke...](https://openid.net/specs/openid-connect-
core-1_0.html#IDToken)

~~~
candiddevmike
My bad, yes I meant only OAuth.

~~~
user5994461
You were correct though, JWT was not part of the OIDC standard. JWT was
created separately and added retroactively later as the standard token format.

------
brujoand
The one thing that really bugs me about the OAuth flow is what is described as
step 3. When the application who wants to access data on your behalf is
redirected to a login page where the user enters credentials and grants
access.

In many apps, these login redirects happen inside the app window, hiding the
url. And even if the URL isn’t hidden, there’s suddenly a browser window
inside my app and many unconscious “security checks” fail to load.

I’d much rather have the OAuth provider send me an email or get a notification
that can be actioned within the OAuth providers app so that I know I’m not
giving my credentials to something that looks like the OAuth providers sign in
page.

~~~
qes
I never understood this either. So many apps pop up a window to enter my
credentials to Google or Facebook or whatever in a manner that just screams
don't put your password in here you have no idea who's hosting this form.

------
archsurface
I look forward to reading this, because I'm currently unconvinced it is
possible.

------
bogomipz
This was a really well-written post. I really liked the learn by doing
approach accompanied by flow diagrams. It's easy to get lost in the weeks with
OAAuth terminology and this really kept good focus. I also looked at some of
the author's other posts on things Protobufs and Tries and found them
similarly enjoyable. I look forward to reading future posts and hope you post
them here as well.

~~~
bswamina
Thanks for the encouragement ... started posting to Hacker News starting this
year and will continue going forward

------
the_af
The article briefly mentions that the Implicit Grant is a less secure and more
simplified version of the Authorization Code grant, but then it doesn't
elaborate (or it's possible I missed that bit). In an introductory article
such as this, I think it's important to explain _why_ it's less secure --
otherwise the Authorization Code grant seems like an unnecessary complication.

~~~
sjroot
The implicit grant returns an access token directly upon authorization being
granted. By removing the additional network request, it can make your system
vulnerable via manipulation of redirect URLs. if you’re implementing an OAuth
2 server, you can address this by validating the provided redirect URLs, but
you should be doing that regardless.

My advice is to just always use the auth code grant with the PKCE extension.
TLDR of that extension:

1) client generates a “secret key” that it sends with the authorization
request. 2) server associates that key with the authorization code it returns
to the authorized client 3) client must present that key again in order to
exchange the authorization code for the access token.

Prevents the authorization code from being intercepted and abused.

~~~
the_af
Oh, I wasn't clear: I understand the implicit grant and I indeed worked on the
implementation of an authorization server in a past job (we validated redirect
URLs, indeed!). My point is that OAuth flows are confusing enough for a
beginner that it's important to explain why seemingly unnecessary hoops are
there. This article doesn't (as far as I can see).

~~~
sjroot
Yeah, I gathered you knew what you were talking about after I had already
posted my comment lol. Just left it up in case any others have that question.
:D

------
ablekh
Would you think that, for an early-stage SaaS startup (enterprise B2B focus),
the _optimal strategy_ for implementing AuthN/AuthZ would be to use a managed
service (e.g., Auth0) for MVP development and after that (perhaps, during
pilots phase) migrate to an open source solution (e.g., Keycloak)?

~~~
anderspitman
Do you need to provide access to third-party apps? If not you probably don't
need oauth. Just use session cookies.

~~~
ablekh
Thank you for your comment. Yes, I'm planning to allow running third-party
apps on the platform (the exact delivery options and relevant architectural
details are still under consideration). My understanding is that using JWTs is
the current best practice and much preferred way for authentication vs. the
session-based approach. The platform that I plan to build should be both
highly scalable and highly secure. I think that session cookies is not the
right approach for these requirements, even if I would not need to allow
running third-party apps. I'm curious about what people here think about this
and hope that they will chime in. (I also would need SSO, external IdP
integration, clustering, MFA, maybe passwordless authentication etc., hence my
preference for managed services like Auth0. The idea is to focus on my core
competencies and outsource important but non-core services to relevant solid
providers, based on availability and feasibility, at least, for the near-to-
mid term.)

~~~
anderspitman
Personally I don't think it's worth worrying about scaling like that until you
actually need to. There are other reasons to choose JWTs, but I don't think
scalability is a good one early on.

~~~
ablekh
Thank you for sharing your thoughts. I'm not worried about scaling and other
aspects, but I do think about them. In my opinion, architectural decisions are
the most important ones (across technological dimension) and fixing wrong or
suboptimal architectural decisions is costly and/or difficult and sometimes
outright not feasible.

~~~
anderspitman
True, but you can further break architectural decisions down into those that
are easy to change and those that aren't. If something is easy to change you
may as well implement the simple version first.

------
ratiolat
The main confusion probably comes from the name Oauth, which seems to suggest
that it is about Single Sign On/authentication, while in reality it's about
granting site A access to your data at site B.

~~~
patmorgan23
That's what Oauth is though. Oauth is NOT a single sign-on technology, it's
about granting access to data across services. OpenID is a single sign-on
protocol built on top of Oauth.

~~~
sjroot
> That’s what Oauth is though.

Splitting hairs but no, Oauth has nothing to do with authentication. An
introductory article like this should address the distinction between
authentication and authorization in the first section IMO.

~~~
tasogare
> the distinction between authentication and authorization

Distinction which is totally useless in practice as you certainly won’t have
authorization without authentication.

~~~
caseysoftware
The distinction is irrelevant if you just consider that authorization (authZ)
always happens after authentication (authN) _but_ it is important when you
realize that different components/systems/protocols might be used in each.

At that point, the separation is more about capabilities/responsibilities than
"does it happen?"

(This is what I do in my day job.)

------
amingilani
I really wish banks would read this.

------
bitwarrior
Can we update the link to point to the actual article?

[https://www.polarsparc.com/xhtml/OAuth2-OIDC.html](https://www.polarsparc.com/xhtml/OAuth2-OIDC.html)

~~~
bswamina
will be happy to change ... there doesn't a way to edit the post ... any
suggestions ?

~~~
ayewo
Email the mods using the address in the “Contact” hyperlink at the bottom of
this page: hn@ycombinator.com.

