
What is WorkOS?
WorkOS is a platform that provides enterprise-ready features for your application, such as Single Sign-On (SSO), Directory Sync, and Audit Logs. It is known for its open-source projects like Radix. They have SDKs in several language (javascript, ruby, java, go, …), so whichever stack you have, there should be and SDK for you.
If you want to know more, WorkOS also have an amazing blog with specific posts about their product, but also more generic ones about OAuth, Jwt tokens, integrations with other vendors, etc.
Authentication Flow
Let’s review how the authentication workflow would work using WorkOS as a third party authentication provider. Below is a diagram illustrating the different calls that an app would make to authenticate a user in this situation:
sequenceDiagram
participant User
participant App
participant WorkOS
User->>App: Login Request
App->>WorkOS: Redirect to WorkOS
WorkOS->>User: Login Page
User->>WorkOS: Submit Credentials
WorkOS->>App: Callback with Auth Code
App->>WorkOS: Exchange Auth Code for Tokens
WorkOS->>App: Access and ID Tokens
App->>User: Authenticated Session
The user logs in through the application, which redirects them to WorkOS for authentication. After the user submits their credentials, WorkOS returns access and ID tokens to the application, establishing an authenticated session.
Implementation example
So your app needs to have two endpoints used for the authentication process:
/login
to redirect the user to the WorkOS login pageapp.get('/login', (req, res) => { const authorizationUrl = workos.sso.getAuthorizationURL({ provider: 'authkit', clientID: 'your_client_id', redirectURI: 'http://localhost:3000/callback', }); res.redirect(authorizationUrl); });
/callback
to handle the callback from WorkOS and exchange the auth code from the login for the user profile and tokenapp.get('/callback', async (req, res) => { const { code } = req.query; const { profile } = await workos.sso.getProfileAndToken({ code, clientID: 'your_client_id', }); // Handle authenticated user profile res.json(profile); });
The callback url is passed to workos when getting the authorization url (for the login page), which means, only valid callback set in the WorkOS dashboard can be used!
The callback can be a local address (e.g. http://localhost:3000/callback
) for development or a public address for production.
But how is Workos calling it, since it’s local? 🤔
That’s because WorkOS is calling the callback from the user’s browser (so it’s the user’s browser that is calling the local address).
You can find more info and different implementation in the WorkOS documentation.
More about AuthKit
If you have noticed, we’re using the authkit to login in the implementation example, which is the self-hosted WorkOS login page.
The WorkOS AuthKit allows you to abstract the authentication process, which removes the need for a backend server to handle the authentication process if using Remix or Next.JS! Below is a diagram showing the interaction between a remix frontend and the AuthKit:
flowchart TD
subgraph App
frontend -->|rely on| authkitSDK[authkit SDK]
authkitSDK
end
User -->|click on login| frontend
authkitSDK -->|login through| authkitApp[authkit App]
authkitApp -->|redirect| frontend
subgraph Workos
authkitApp
end
The session is encrypted and securely passed through a cookie 🍪 in the response as wos-session
,
ensuring that user data is protected during the authentication process (only the remix server side has the key to decrypt it).
The authkit approach is recommended by the WorkOS team and provide a straightforward login experience.
They have developed the SDKs to make it easy to integrate with your frontend (for example the @workos-inc/authkit-remix
for remix).
Plus you can easily add multiple SSO providers and more out of the box!
Syncing Data with WorkOS
You can retrieve user information via the WorkOS webhook or WorkOS event api. This is important if you want to sync user data with your application or have event-based actions.
While the webhook is more immediate, the event queue is more reliable and can handle a higher volume of events.
- Webhooks events are signed and are coming from a set of IPs that you can whitelist.
- There is a retry mechanism in case your application fails to read the event.
- You need to create a public endpoint to receive the events.
- Events are accessible via the WorkOS API and can be consumed at your own pace va the SDK.
For each option there are multiple event types you can subscribe to.
The preferred option pushed by WorkOS is to use the event API, as it is more reliable and can handle a higher volume of events.
import { WorkOS } from '@workos-inc/node';
const workos = new WorkOS(process.env.WORKOS_API_KEY);
const listOfEvents = await workos.events.listEvents({
events: [
'dsync.activated',
'dsync.deleted',
'dsync.user.created',
'dsync.user.updated',
'dsync.user.deleted',
],
});
Here is the example to retrieve a some events using the workos javascript SDK from the documentation. We’d be only interested in the directory sync and user events in this case, but there are more events available to fit your needs. All the events available via the API are also sent to the webhook (if configured).
The workos documentation is excellent and the team very approachable (they can make simple changes on the fly to help you out). I’d recommend checking it out if you’re looking for a third party authentication provider 👍.