Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ul blog improvements #1522

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 77 additions & 11 deletions _source/_posts/2024-04-30-express-universal-logout.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ While viewing your database locally, you'll also see an org table. By clicking t
- client_secret = ${ClientSecret}
- apikey = 131313

>**Note**: You can also get these OIDC-related endpoints by visiting this metadata URL `https://{yourOktaOrg}/.well-known/openid-configuration` provided by the [Okta Org authorization server](https://developer.okta.com/docs/concepts/auth-servers/#discovery-endpoints-org-authorization-servers).

### Create a test user

To test whether UL works for our app, we'll create a user on Okta whose account we'll forcibly sign out.
Expand Down Expand Up @@ -105,7 +107,7 @@ import { Router } from 'express';
export const universalLogoutRoute = Router();
```

Let's add the UL route to this file:
Let's add the UL route to this file as well:

```ts
import { Router } from 'express';
Expand Down Expand Up @@ -183,22 +185,72 @@ universalLogoutRoute.post('/global-token-revocation', async (req, res) => {
if (!req.body) {
res.status(400);
}

// Find the user by email linked to the org id associated with the API key provided
const domainOrgId = req['user']['id']

// Find the user
const newRequest:IRequestSchema = req.body;
const { email } = newRequest.sub_id;
const user = await prisma.user.findFirst({
where: {
email: email,
org: { id: domainOrgId },
email: email
},
});
return res.sendStatus(httpStatus);

// 404 User not found
// 404 User not found
if (!user) {
res.sendStatus(404);
}

});

universalLogoutRoute.use((err,req,res,next) => {
if(err){
return res.sendStatus(404)
}
})
```
The apps/api/src/universalLogout.ts file now looks like the following:

```ts
import { Router } from 'express';
export const universalLogoutRoute = Router();
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();

interface IRequestSchema {
'sub_id': {format:string; email: string};
}
universalLogoutRoute.post('/global-token-revocation', async (req, res) => {
// 204 When the request is successful
const httpStatus = 204;

// 400 If the request is malformed
if (!req.body) {
res.status(400);
}

// Find the user
const newRequest:IRequestSchema = req.body;
const { email } = newRequest.sub_id;
const user = await prisma.user.findFirst({
where: {
email: email
},
});
return res.sendStatus(httpStatus);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?? am i missing a paren indention? This looks like you are returning out of the method first, then there's code that will never get hit to check if the user doesn't exist. I don't understand. is the intent for the 404 check to move higher?


// 404 User not found
if (!user) {
res.sendStatus(404);
}

});

universalLogoutRoute.use((err,req,res,next) => {
if(err){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's an error and why are they all 404?

return res.sendStatus(404)
}
})
```

>**Checkpoint**: Now is an excellent time to test our code.
Expand Down Expand Up @@ -405,6 +457,20 @@ universalLogoutRoute.use((err,req,res,next) => {
}
})
```
So now let's do another test to make sure the authentication piece we added is working. We'll need to modify our cURL request to include an Authorization header with a `Bearer 131313`. This should result in a 204 response.

```http
curl --request POST \
--url http://localhost:3333/global-token-revocation \
--header 'Authorization: Bearer 131313' \
--header 'Content-Type: application/json' \
--data '{
"sub_id": {
"format": "email",
"email": "[email protected]"
}
}'
```

Moving right along, now that we have the target user of a specific org. Let's figure out how to target their application session and end it.

Expand Down Expand Up @@ -527,7 +593,7 @@ universalLogoutRoute.post('/global-token-revocation', async (req, res) => {
}

// Find the user by email linked to the org id associated with the API key provided
const domainOrgId = req['user']['id']
const domainOrgId = req['user']['id']
const newRequest:IRequestSchema = req.body;
const { email } = newRequest.sub_id;
const user = await prisma.user.findFirst({
Expand Down Expand Up @@ -602,7 +668,7 @@ if (!res.ok)
}}
```

The onNewTask function will now look like this:
The onNewTask function will now look like this with a change made only to the `onNewTAsk` function:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should re-evaluate this sentence. It seems repetitive. Also change casing for onNewTAsk


```ts
import { useEffect, useState } from 'react';
Expand Down Expand Up @@ -635,8 +701,8 @@ export const Todos = () => {
});

if (!res.ok){if (res.status === 401) {
// Redirect user back to the sign in page
window.location.href = '/';
// Redirect user back to the sign in page
window.location.href = '/';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity, why are using window API here to redirect to home. I thought this is handled already inside the todo app, can't we use React Router?

} else {
// Handle other errors
throw new Error('Error occurred while fetching data');
Expand Down
Loading