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

Merged
merged 4 commits into from
Sep 23, 2024
Merged
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
92 changes: 81 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,73 @@ 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
},
});

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

return res.sendStatus(httpStatus);
});

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
},
});

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

return res.sendStatus(httpStatus);

});

universalLogoutRoute.use((err,req,res,next) => {
if(err){
isemona marked this conversation as resolved.
Show resolved Hide resolved
return res.sendStatus(404)
}
})
```

>**Checkpoint**: Now is an excellent time to test our code.
Expand Down Expand Up @@ -398,13 +451,30 @@ universalLogoutRoute.post('/global-token-revocation', async (req, res) => {
res.sendStatus(404);
}

return res.sendStatus(httpStatus);
});

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

return res.sendStatus(404)
}
})
```
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 +597,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 +672,7 @@ if (!res.ok)
}}
```

The onNewTask function will now look like this:
The `onNewTask` function will now look like this:

```ts
import { useEffect, useState } from 'react';
Expand Down Expand Up @@ -635,8 +705,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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will pick up on this in next PR

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