Skip to content

Getting Started

Install

npm

bash
pnpm add @jmondi/oauth2-server
bash
npm install --save @jmondi/oauth2-server
bash
yarn add @jmondi/oauth2-server

The Authorization Server

The AuthorizationServer depends on the repositories. By default, no grants are enabled; each grant is opt-in and must be enabled when creating the AuthorizationServer.

You can enable any grant types you would like to support.

typescript
const authorizationServer = new AuthorizationServer(
  clientRepository,
  accessTokenRepository,
  scopeRepository,
  "secret-key",
  {} // optional configuration
);
authorizationServer.enableGrantType("client_credentials");
authorizationServer.enableGrantType("refresh_token");
authorizationServer.enableGrantType({
  grant: "authorization_code",
  userRepository, 
  authorizationCodeRepository,
});

See the configuration documentation for a full list of config options.

The Token Endpoint

The /token endpoint is a back channel endpoint that issues a usable access token.

typescript
app.post("/token", async (req: Express.Request, res: Express.Response) => {
  try {
    const oauthResponse = await authorizationServer.respondToAccessTokenRequest(req);
    return handleExpressResponse(res, oauthResponse);
  } catch (e) {
    handleExpressError(e, res);
    return;
  }
});

The Authorize Endpoint

The /authorize endpoint is a front channel endpoint that issues an authorization code. The authorization code can then be exchanged to the AuthorizationServer endpoint for a useable access token.

The endpoint should redirect the user to login, and then to accept the scopes requested by the application, and only when the user accepts, should it send the user back to the clients redirect uri.

typescript
import { requestFromExpress } from "@jmondi/oauth2-server/express";

app.get("/authorize", async (req: Express.Request, res: Express.Response) => {
  try {
    // Validate the HTTP request and return an AuthorizationRequest.
    const authRequest = await authorizationServer.validateAuthorizationRequest(request, requestFromExpress(req));

    // You will probably redirect the user to a login endpoint. 
    if (!req.user) {
      req.redirect("/login")
      return;
    }
    // After login, the user should be redirected back with user in the session.
    // You will need to manage the authorization query on the round trip.
    // The auth request object can be serialized and saved into a user's session.

    // Once the user has logged in set the user on the AuthorizationRequest
    authRequest.user = req.user;
    
    // Once the user has approved or denied the client update the status
    // (true = approved, false = denied)
    authRequest.isAuthorizationApproved = getIsAuthorizationApprovedFromSession();

    // If the user has not approved the client's authorization request, 
    // the user should be redirected to the approval screen.
    if (!authRequest.isAuthorizationApproved) {
      // This form will ask the user to approve the client and the scopes requested.
      // "Do you authorize Jason to: read contacts? write contacts?"
      req.redirect("/scopes")
      return;
    }

    // At this point the user has approved the client for authorization.
    // Any last authorization requests such as Two Factor Authentication (2FA) can happen here.


    // Redirect back to redirect_uri with `code` and `state` as url query params.
    const oauthResponse = await authorizationServer.completeAuthorizationRequest(authRequest);
    return handleExpressResponse(res, oauthResponse);
  } catch (e) {
    handleExpressError(e, res);
  }
});

Revoke Token

Note

Implementing this endpoint is optional, but recommended. RFC7009 “OAuth 2.0 Token Revocation”

The /token/revoke endpoint is a back channel endpoint that revokes an existing token.

typescript
app.post("/token/revoke", async (req: Express.Request, res: Express.Response) => {
  try {
    const oauthResponse = await authorizationServer.revoke(req);
    return handleExpressResponse(res, oauthResponse);
  } catch (e) {
    handleExpressError(e, res);
    return;
  }
});

Released under the MIT License.