Skip to content

Commit d372b0f

Browse files
committed
lesson 5
1 parent 1c1c081 commit d372b0f

File tree

6 files changed

+208
-1
lines changed

6 files changed

+208
-1
lines changed
565 KB
Loading
444 KB
Loading
94.6 KB
Loading
35 KB
Loading

module4-authentication-and-security/r1.1.1-authentication-persistence/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ let listener = app.listen(5000, function () {
4141

4242
In the code snippet above, we configured the session storage using `app.use()` and created a new session instance with the configuration below:
4343

44-
- `secret`: a token that will be used to encrypt the data and cookies. It can also be a universal `APP_SECRET` defined in the environment variables. This must be a random secret generated by secure random generators.
44+
- `secret`: a token that will be used to encrypt the data and cookies. It can also be a universal `APP_SECRET` defined in the environment variables. This must be a random secret generated by secure random generators and it shouldn't be shared with anyone.
4545
- `cookie`: cookie parameters that will be set in the client. Because our development environment doesn't have HTTPs, we turned off `secure`. In a production environment, the cookie should only be sent in secure contexts so secure should be true.
4646

4747
This initialization would eventually activate the `session` object in each request, and a `Set-Cookie` header to each response when a session is created. The cookie will contain the `sessionID` that the server can use to read the session storage and grab the session data.
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# APIs auth schemes: Single Sign-On, OpenID Connect, and OAuth
2+
3+
In this lesson, we will explore authorization and authentication standards for cross-domain sessions and services. We will tackle single sign-on as a way to have universal account for multiple services. Then we wrap that with the OpenID Connect standard that offers decentralized authentication protocol which operates over OAuth standard. OAuth in its turn offers a way for apps to communicate between each other on your behalf as an authorization framework. The learning objectives are:
4+
5+
- You will get to know how to use each of these standards and how do they work
6+
- The difference between ID Tokens, Access Tokens, and Refresh Tokens
7+
- When and why we would need OAuth
8+
- What is scoped access control
9+
10+
## Single Sign-On
11+
12+
Single sign-on (SSO) is an authentication method that enables users to securely authenticate with multiple applications and websites by using just one set of credentials. It occurs when a user logs in to one application and is then signed in to other applications automatically, regardless of the platform, technology, or domain the user is using. The user signs in only one time, hence the name of the feature (Single Sign-on).
13+
14+
For example, if you log in to a Google service such as Gmail, you are automatically authenticated to YouTube, Google Drive, AdSense, Google Analytics, and other Google apps. Likewise, if you log out of your Gmail or other Google apps, you are automatically logged out of all the apps; this is known as Single Logout.
15+
16+
SSO provides a seamless experience for users when using your applications and services. Instead of having to remember separate sets of credentials for each application or service, users can simply log in once and access your full suite of applications.
17+
18+
Whenever users go to a domain that requires authentication, they are redirected to the authentication domain where they may be asked to log in. If the user is already logged in at the authentication domain, they can be immediately redirected to the original domain without signing in again.
19+
20+
### How does SSO work?
21+
22+
SSO works based upon a trust relationship set up between an application, known as the service provider, and an identity provider, like [OneLogin](https://www.onelogin.com/) or [Auth0](https://auth0.com/). This trust relationship is often based upon a certificate that is exchanged between the identity provider and the service provider. This certificate can be used to sign identity information that is being sent from the identity provider to the service provider so that the service provider knows it is coming from a trusted source. In SSO, this identity data takes the form of JWTs which contain identifying bits of information about the user like a user’s email address or a username.
23+
24+
The login flow usually looks like this:
25+
26+
1. A user browses to the application or website they want access to, aka, the Service Provider.
27+
2. The Service Provider sends a token that contains some information about the user, like their email address, to the SSO system, aka, the Identity Provider, as part of a request to authenticate the user.
28+
3. The Identity Provider first checks to see whether the user has already been authenticated, in which case it will grant the user access to the Service Provider application and skip to step 5.
29+
4. If the user hasn’t logged in, they will be prompted to do so by providing the credentials required by the Identity Provider. This could simply be a username and password or it might include some other form of authentication like a One-Time Password (OTP).
30+
5. Once the Identity Provider validates the credentials provided, it will send a token back to the Service Provider confirming a successful authentication.
31+
6. This token is passed through the user’s browser to the Service Provider.
32+
7. The token that is received by the Service Provider is validated according to the trust relationship that was set up between the Service Provider and the Identity Provider during the initial configuration.
33+
8. The user is granted access to the Service Provider.
34+
35+
![SSO Workflow](../assets/sso-workflow.png)
36+
37+
### SSO Implementation
38+
39+
SSO Implementation in your backend app will depend heavily on the Identity Provider that you choose. Most IdP use the OpenID Connect (OIDC) protocol to offer SSO. However, some enterprises rely on [Security Assertion Markup Language (SAML)](https://www.onelogin.com/learn/saml) open standard to exchange authorization and identity.
40+
41+
We won't be covering SAML for SSO in this lesson, but you can learn more on how to use OIDC in your application in the next section.
42+
43+
## OpenID Connect
44+
45+
OpenID is also an open standard and decentralized authentication protocol promoted by the non-profit OpenID Foundation. It allows users to be authenticated by cooperating sites (known as relying parties, or RP) using a third-party identity provider (IdP) service, eliminating the need for webmasters to provide their own ad hoc login systems, and allowing users to log into multiple unrelated websites without having to have a separate identity and password for each.
46+
47+
If you ever used Sign in with Google, or Sign in with Github, then you've used the OpenID standard that was coupled with OAuth protocol to share your identity with 3rd party applications.
48+
49+
Let's take Github's as an example, when you click the sign in button, the app (RP) will redirect your to the Github sign in page that is hosted on github.com domain. When you sign in, you will be redirected to the permissions or authorization page where it will ask for your consent to authorize sharing your identity with the Service Provider (RP). Once you give consent, Github will redirect you to a callback URL that the service provider already shared with Github and attach a unique authorization code to the request. The app or service provider will use that code to contact the IdP for your profile.
50+
51+
![OpenID Connect Flowchart](../assets/oidc-flowchart-trans.png)
52+
53+
### OpenID vs OpenID Connect
54+
55+
It might get confusing when you start searching within these standards. You will find there is a distinction between OpenID and OpenID Connect, each using a different response type and protocol. For now, OpenID older revisions are mostly deprecated and the acceptable standard is OpenID Connect over OAuth 2.0. Quoting a great [answer on Stack Overflow](https://security.stackexchange.com/a/130411) talking more about this topic.
56+
57+
#### Simple Terms
58+
59+
- OpenID is about verifying a person's identity (authentication).
60+
- OAuth is about accessing a person's stuff (authorization).
61+
- OpenID Connect does both.
62+
63+
All three let a person give their username/password (or other credential) to a trusted authority instead of to a less trusted app.
64+
65+
#### More Details
66+
67+
To understand something, look at its history.
68+
69+
OpenID & OAuth have developed on parallel tracks and in 2014 merged into OpenID Connect. Throughout their history, OpenID and OAuth have let an app use a trusted authority to handle private user credentials. Whereas OpenID let the authority verify a user's identity, OAuth let the authority grant limited access to a user's stuff.
70+
71+
**OpenID 1.0** (2006) lets an app ask an authority for proof that an end user owns an identify (a URL).
72+
73+
- End user to app: I am Steve A. Smith.
74+
- App to authority: Is this Steve A. Smith?
75+
- The end user and authority speak for a moment.
76+
- Authority to app: Yes, that is Steve A. Smith.
77+
- OpenID 2.0 (2007) does the same, but adds a second identity format (XRI) and adds flexibility to how the end user specifies the identity and authority.
78+
79+
**OpenID Attribute Exchange 1.0** (2007) extends OpenID 2.0 by letting an app fetch & store end user profile information with the authority - in addition to verifying the end user's identity.
80+
81+
- End user to app: I am Steve A. Smith.
82+
- App to authority: Is this Steve A. Smith? Oh, and if it is, also fetch me his email address and phone number.
83+
- The end user and authority speak for a moment.
84+
- Authority to app: Yes, that is Steve A. Smith. His email is [email protected] and phone number is 123-456-7890.
85+
86+
**OAuth 1.0** (2010) lets an end user grant an app limited access to resources on a third-party server that an authority owns.
87+
88+
- App to end user: We'd like to access your pictures on some other server.
89+
- The end user and authority speak for a moment.
90+
- Authority to app: Here is an access token.
91+
- App to third-party server: Here is the access token that proves I am allowed to access pictures for an end user.
92+
93+
**OAuth 2.0** (2012) does the same thing as OAuth 1.0 but with a completely new protocol.
94+
95+
**OpenID Connect** (2014) combines the features of OpenID 2.0, OpenID Attribute Exchange 1.0, and OAuth 2.0 in a single protocol. It allows an application to use an authority...
96+
97+
- to verify the end user's identity,
98+
- to fetch the end user's profile info, and
99+
- to gain limited access to the end user's stuff.
100+
101+
### Consuming OpenID standard
102+
103+
To use OpenID standard for authentication in your app, you need to register an OAuth client application to the provider or providers you would like to use.
104+
105+
Most mainstream identity providers offer identity using OAuth protocol with OIDC, so you need to create the application using the provider's platform.
106+
107+
Once the app is created, you will be handed a client ID and a client secret which shouldn't be shared with anyone. Some providers like facebook also require that you define your needed app scopes when creating the app. We will talk about scopes in the next section, but for identity, the scope you need is `openid`. This scope makes the identity provider share an ID token with your app that contains the user details, like thier name, email, profile picture, and so on.
108+
109+
While this is an open standard that should, more or less, have similiar implementations, providers tend to adjust the flow or the output. To simplify consuming federated identity via OpenID, there are libraries out there that makes the integration very straightforward. One such library is [Passport.js](https://www.npmjs.com/package/passport).
110+
111+
### Passport.js
112+
113+
Passport is [Express](http://expressjs.com/)-compatible authentication middleware for [Node.js](http://nodejs.org/).
114+
115+
Passport's sole purpose is to authenticate requests, which it does through an extensible set of plugins known as _strategies_. Passport does not mount routes or assume any particular database schema, which maximizes flexibility and allows application-level decisions to be made by the developer. The API is simple: you provide Passport a request to authenticate, and Passport provides hooks for controlling what occurs when authentication succeeds or fails.
116+
117+
What's cool about Passport, is you can combine multiple providers in your app, giving users the choice to use the provider they prefer while delegating the implementation details to Passport.js.
118+
119+
### Passport.js strategies
120+
121+
[Passport](https://www.npmjs.com/package/passport) npm library comes with basic middleware and implementation, however, to use it, you need to also install the required plugins for your authentication routes. These plugins are called [strategies](http://www.passportjs.org/packages/).
122+
123+
If your app uses email and password to authenticate users, then you will need to install the [`passport-local`](http://www.passportjs.org/packages/passport-local/) strategy. And if you are also adding logging in with google, then you will need to install the [`passport-google`](http://www.passportjs.org/packages/passport-google/) strategy. And so on.
124+
125+
Below is an example to add Login with Github to your app using [`passport-github2`](http://www.passportjs.org/packages/passport-github2/) strategy
126+
127+
```js
128+
passport.use(
129+
new GitHubStrategy(
130+
{
131+
clientID: GITHUB_CLIENT_ID,
132+
clientSecret: GITHUB_CLIENT_SECRET,
133+
callbackURL: "http://127.0.0.1:3000/auth/github/callback",
134+
},
135+
function (accessToken, refreshToken, profile, done) {
136+
User.findOrCreate({ githubId: profile.id }, function (err, user) {
137+
return done(err, user);
138+
});
139+
}
140+
)
141+
);
142+
```
143+
144+
The code sets up the strategy with your OAuth Github Client credentials, and a callback URL that Github will contact to share authorization code. Once the identity is fetched, we need to register a user or log them in using thier Github `profile.id`.
145+
146+
To authenticate requests, use passport.authenticate(), specifying the 'github' strategy.
147+
148+
```js
149+
app.get(
150+
"/auth/github",
151+
passport.authenticate("github", { scope: ["user:email"] })
152+
);
153+
154+
app.get(
155+
"/auth/github/callback",
156+
passport.authenticate("github", { failureRedirect: "/login" }),
157+
function (req, res) {
158+
// Successful authentication, redirect home.
159+
res.redirect("/");
160+
}
161+
);
162+
```
163+
164+
In the last code snippet we used the scope `user:email` to also fetch the user email from Github whether private or public. That is only if we needed the emails because the scope `openid` will only share an identity and public emails.
165+
166+
[![Edit Github OpenID](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github-openid-lpuy4?fontsize=14&hidenavigation=1&theme=dark)
167+
168+
## OAuth 2.0
169+
170+
Now that we covered SSO, and OpenID Connect, we can cover the OAuth 2.0 standard that OIDC is built upon.
171+
172+
If you remember, back in the days (c. 2005), when you logged in to Yahoo mail, and you wanted to import your emails and contacts from another provider, like Gmail, Yahoo would ask you to share your Gmail password so they can login as you to Gmail, and download your data, then upload it to Yahoo's server! Sneaky! That was because at the time there wasn't a standard that allow communication between services on your behalf. You have to trust Yahoo with your password, and that would give them full access and control over your Gmail!
173+
174+
This scheme was prominent in many apps, like asking for your bank username and password, to read your bank statement and offer you budget planning.
175+
176+
![Shady Budget Planner](../assets/shady-budget-planner.jpg)
177+
_Image rights belong to [Okta Developers](https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc)_
178+
179+
You should never be required to share your username and password, your credentials, to another service. There’s no guarantee that an organization will keep your credentials safe, or guarantee their service won’t access more of your personal information than necessary. It might sound crazy, but some applications still try to get away with this!
180+
181+
To the rescue comes OAuth, an agreed-upon standard to securely allow one service to access data from another.
182+
183+
Suppose you are building an application that allows users to read their Google Drive files as well as upload files and organize documents. In order to access the user's GDrive, you need to direct the user to Google so that they can share with you access to their GDrive. Then Google will share an access token with you on the user behalf that gives your app access to user's resources in google drive.
184+
185+
![Open Auth Flowchart](../assets/oauth-flowchart.png)
186+
187+
Using the access token, and the provided permissions, the service provider can keep accessing the user's resources as long as the access token is valid. It can get expired, in that case a the refresh token can be used to request another access token.
188+
189+
One important concept to remember, is to not mix between authentication and authorization in OAuth, OpenID Connect uses the OAuth standard for simplicity and easier integration, however they are completely different in terms of usage concept. That's why we aren't using Passport for Authorization because it has the sole purpose of authentication. For more details, head to this [article by Okta Developers](https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc).
190+
191+
### Requesting Authorization
192+
193+
You can request authorization in 1 step when the user logs in, in that flow, you request the `openid` scope along with other scopes your app needs. However, in that flow, your permissions need to be clearly stated to the user with their use cases. Otherwise a user might refuse to grant certain permissions.
194+
195+
The other flow, is to seperate authorization over multiple steps, when needed. You can start with base scopes, like profile and read access, then whenever your app needs more access, you clarify to the user, and direct them to the resource owner for that additional scope or permission.
196+
197+
In all cases, you need to use an OAuth 2.0 client library like [`client-oauth2`](https://www.npmjs.com/package/client-oauth2), or [`simple-oauth2`](https://www.npmjs.com/package/simple-oauth2) to communicate with OAuth providers. Sometimes, the providers have their own library to use like [Google OAuth client libraries](https://developers.google.com/identity/protocols/oauth2/web-server#httprest) and [Octokit](https://github.com/octokit).
198+
199+
You can check the codesandbox below for live implementation of OAuth to read a user's private repository after they login with Github.
200+
201+
[![Edit Github OAuth](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github-oauth-q576g?fontsize=14&hidenavigation=1&theme=dark)
202+
203+
### OAuth Server
204+
205+
So far, what we've seen and implemented are consuming an OAuth server using and OAuth client. However, if your application contains resources that you want to give 3rd party services access to, you need to integrate your own OAuth server.
206+
207+
To integrate and OAuth server, most of the heavy lifting need to be done by your app, like creating the API and enforcing scopes, however, there are libraries out there tha makes the process of issuing client ids, secrets, and access tokens easier. You can do your own research on this topic.

0 commit comments

Comments
 (0)