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

Add typescript defs new config #46

Merged
merged 4 commits into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
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
14 changes: 8 additions & 6 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ Please see the [Getting Started section of the README](https://github.com/auth0/

The `auth()` middleware has a few configuration keys that are required for initialization.

- **`appSessionSecret`** - The secret used to derive an encryption key for the user identity in a session cookie. It must be a string, an array of strings, or `false` to skip this internal storage and provide your own session mechanism in `getUser`. When array is provided the first member is used for signing and other members can be used for decrypting old cookies, this is to enable appSessionSecret rotation. This can be set automatically with an `APP_SESSION_SECRET` variable in your environment.
- **`baseURL`** - The root URL for the application router. This can be set automatically with a `BASE_URL` variable in your environment.
- **`clientID`** - The Client ID for your application. This can be set automatically with a `CLIENT_ID` variable in your environment.
- **`issuerBaseURL`** - The root URL for the token issuer with no trailing slash. In Auth0, this is your Application's **Domain** prepended with `https://`. This can be set automatically with an `ISSUER_BASE_URL` variable in your environment.
- **`appSessionSecret`** - The secret used to derive an encryption key for the user identity in a session cookie. Set this to `false` to skip this internal storage and provide your own session mechanism in `getUser`. This can be set automatically with an `APP_SESSION_SECRET` variable in your environment. It must be a string or an array of strings. When array is provided the first member is used for signing and other members can be used for decrypting old cookies, this is to enable appSessionSecret rotation.

If you are using a response type that includes `code` (typically combined with an `audience` parameter), you will need an additional key:

Expand All @@ -21,23 +21,25 @@ If you are using a response type that includes `code` (typically combined with a

Additional configuration keys that can be passed to `auth()` on initialization:

- **`appSessionCookie`** - Object defining application session cookie attributes. Allowed keys are `domain`, `httpOnly`, `path`, `secure`, and `sameSite`. Defaults are `true` for `httpOnly` and `Lax` for `sameSite`.
- **`appSessionDuration`** - Integer value, in seconds, for application session duration. Set to `0` to indicate the cookie should be ephemeral (no expiration). Default is 7 days.
- **`appSessionName`** - String value for the cookie name used for the internal session. This value must only include letters, numbers, and underscores. Default is `identity`.
- **`auth0Logout`** - Boolean value to enable Auth0's logout feature. Default is `false`.
- **`authorizationParams`** - Object that describes the authorization server request. [See below](#authorization-params-key) for defaults and more details.
- **`clockTolerance`** - Integer value for the system clock's tolerance (leeway) in seconds for ID token verification. Default is `60`.
- **`getUser`** - Asynchronous function that receives a token set and returns the profile for `req.openid.user`. This runs on each application page load for authenticated users. Default is [here](lib/getUser.js).
- **`errorOnRequiredAuth`** - Boolean value to throw a `Unauthorized 401` error instead of triggering the login process for routes that require authentication. Default is `false`.
- **`getUser`** - Function that returns the profile for `req.openid.user`. This runs on each application page load for authenticated users. Default is [here](lib/hooks/getUser.js).
- **`handleCallback`** - Function that runs on the callback route, after callback processing but before redirection. Default is [here](lib/hooks/handleCallback.js).
- **`httpOptions`** - Default options object used for all HTTP calls made by the library ([possible options](https://github.com/sindresorhus/got/tree/v9.6.0#options)). Default is empty.
- **`idpLogout`** - Boolean value to log the user out from the identity provider on application logout. Requires the issuer to provide a `end_session_endpoint` value. Default is `false`.
- **`identityClaimFilter`** - Array value of claims to remove from the ID token before storing the cookie session. Default is `['aud', 'iss', 'iat', 'exp', 'nonce', 'azp', 'auth_time']`.
- **`idpLogout`** - Boolean value to log the user out from the identity provider on application logout. Requires the issuer to provide a `end_session_endpoint` value. Default is `false`.
- **`idTokenAlg`** - String value for the expected ID token algorithm. Default is `RS256`.
- **`legacySameSiteCookie`** - Set a fallback cookie with no SameSite attribute when `authorizationParams.response_mode` is `form_post`. Default is `true`.
- **`loginPath`** - Relative path to application login. Default is `/login`.
- **`logoutPath`** - Relative path to application logout. Default is `/logout`.
- **`redirectUriPath`** - Relative path to the application callback to process the response from the authorization server. This value is combined with the `baseUrl` and sent to the authorize endpoint as the `redirectUri` parameter. Default is `/callback`.
- **`required`** - Use a boolean value to require authentication for all routes. Pass a function instead to base this value on the request. Default is `true`.
- **`routes`** - Boolean value to automatically install the login and logout routes. See [the examples](EXAMPLES.md) for more information on how this key is used. Default is `true`.
- **`appSessionDuration`** - Integer value, in seconds, indicating application session length. Set to `0` to indicate the cookie should be ephemeral (no expiration). Default is 7 days.
- **`appSessionName`** - String value for the cookie name used for the internal session. This value must only include letters, numbers, and underscores. Default is `identity`.
- **`appSessionCookie`** - Object defining application session cookie attributes. Allowed keys are `domain`, `httpOnly`, `path`, `secure`, and `sameSite`. Defaults are `true` for `httpOnly` and `Lax` for `sameSite`.

### Authorization Params Key

Expand Down
121 changes: 119 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,144 @@
// Type definitions for express-openid-connect

import { AuthorizationParameters, TokenSet, UserinfoResponse } from 'openid-client';
import { Request, RequestHandler } from 'express';
import { Request, Response, NextFunction, RequestHandler } from 'express';

interface ConfigParams {
/**
* Object defining application session cookie attributes.
*/
appSessionCookie?: SessionCookieConfigParams;

/**
* Integer value, in seconds, for application session duration.
*/
appSessionDuration?: number;

/**
* String value for the cookie name used for the internal session.
*/
appSessionName?: string;

/**
* REQUIRED. The secret(s) used to derive an encryption key for the user identity in a session cookie.
* Can use env key APP_SESSION_SECRET instead.
*/
appSessionSecret: boolean | string | string[];

/**
* Boolean value to enable Auth0's logout feature.
*/
auth0Logout?: boolean;

/**
* URL parameters used when redirecting users to the authorization server to log in.
*/
authorizationParams?: AuthorizationParameters

/**
* REQUIRED. The root URL for the application router.
* Can use env key BASE_URL instead.
*/
baseURL?: string;

/**
* REQUIRED. The Client ID for your application.
* Can use env key CLIENT_ID instead.
*/
clientID?: string;

/**
* The Client Secret for your application.
* Required when requesting access tokens.
* Can use env key CLIENT_SECRET instead.
*/
clientSecret?: string;

/**
* Integer value for the system clock's tolerance (leeway) in seconds for ID token verification.
*/
clockTolerance?: number;

/**
* Throw a 401 error instead of triggering the login process for routes that require authentication.
*/
errorOnRequiredAuth?: boolean;
getUser?: (tokenSet: TokenSet) => undefined | UserinfoResponse;
joshcanhelp marked this conversation as resolved.
Show resolved Hide resolved

/**
* Function that returns the profile for `req.openid.user`.
*/
getUser?: (req: Request, config: ConfigParams) => undefined | UserinfoResponse;

/**
* Function that runs on the callback route, after callback processing but before redirection.
*/
handleCallback?: RequestHandler;

/**
* Default options object used for all HTTP calls made by the library.
*/
httpOptions?: object;

/**
* Array value of claims to remove from the ID token before storing the cookie session.
*/
identityClaimFilter?: string[];

/**
* Boolean value to log the user out from the identity provider on application logout.
*/
idpLogout?: boolean;

/**
* String value for the expected ID token algorithm.
*/
idTokenAlg?: string;

/**
* REQUIRED. The root URL for the token issuer with no trailing slash.
* Can use env key ISSUER_BASE_URL instead.
*/
issuerBaseURL?: string;

/**
* Set a fallback cookie with no SameSite attribute when response_mode is form_post.
*/
legacySameSiteCookie?: boolean;

/**
* Relative path to application login.
*/
loginPath?: string;

/**
* Relative path to application logout.
*/
logoutPath?: string;

/**
* Relative path to the application callback to process the response from the authorization server.
*/
redirectUriPath?: string;

/**
* Require authentication for all routes.
*/
required?: boolean | ((request: Request) => boolean);

/**
* Boolean value to automatically install the login and logout routes.
*/
routes?: boolean;
}

interface SessionCookieConfigParams {
domain?: string;
httpOnly?: boolean;
path?: string;
sameSite?: string;
secure?: boolean;
}

export function auth(params?: ConfigParams): RequestHandler;
export function requiresAuth(): RequestHandler;
export function unauthorizedHandler(): RequestHandler;
54 changes: 27 additions & 27 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ const getUser = require('./hooks/getUser');
const handleCallback = require('./hooks/handleCallback');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just rearranging in this file.


const defaultAuthorizeParams = {
response_type: 'id_token',
response_mode: 'form_post',
response_type: 'id_token',
scope: 'openid profile email'
};

const authorizationParamsSchema = Joi.object().keys({
response_type: Joi.string().required(),
response_mode: [Joi.string().optional(), Joi.allow(null).optional()],
response_type: Joi.string().required(),
scope: Joi.string().required()
}).unknown(true);

Expand All @@ -24,27 +24,10 @@ const appSessionCookieSchema = Joi.object().keys({
secure: Joi.boolean().optional()
}).unknown(false);

// const requiredParams = ['issuerBaseURL', 'baseURL', 'clientID'];
const paramsSchema = Joi.object().keys({
httpOptions: Joi.object().optional(),
issuerBaseURL: Joi.alternatives([ Joi.string().uri(), Joi.string().hostname() ]).required(),
baseURL: Joi.string().uri().required(),
clientID: Joi.string().required(),
clientSecret: Joi.string().optional(),
idTokenAlg: Joi.string().not('none').optional().default('RS256'),
authorizationParams: Joi.object().optional(),
clockTolerance: Joi.number().optional().default(60),
getUser: Joi.func().optional().default(getUser),
handleCallback: Joi.func().optional().default(handleCallback),
required: Joi.alternatives([ Joi.func(), Joi.boolean()]).optional().default(true),
routes: Joi.boolean().optional().default(true),
errorOnRequiredAuth: Joi.boolean().optional().default(false),
auth0Logout: Joi.boolean().optional().default(false),
redirectUriPath: Joi.string().optional().default('/callback'),
loginPath: Joi.string().optional().default('/login'),
logoutPath: Joi.string().optional().default('/logout'),
legacySameSiteCookie: Joi.boolean().optional().default(true),
identityClaimFilter: Joi.array().optional().default(['aud', 'iss', 'iat', 'exp', 'nonce', 'azp', 'auth_time']),
appSessionCookie: Joi.object().optional(),
appSessionDuration: Joi.number().integer().optional().default(7 * 24 * 60 * 60),
appSessionName: Joi.string().token().optional().default('identity'),
appSessionSecret: Joi.alternatives([
// Single string key.
Joi.string(),
Expand All @@ -53,11 +36,28 @@ const paramsSchema = Joi.object().keys({
// False to stop client session from being created.
Joi.boolean().valid([false])
]).required(),
appSessionName: Joi.string().token().optional().default('identity'),
appSessionDuration: Joi.number().integer().optional().default(7 * 24 * 60 * 60),
appSessionCookie: Joi.object().optional(),
idpLogout: Joi.boolean().optional().default(false)
.when('auth0Logout', { is: true, then: Joi.boolean().optional().default(true) })
auth0Logout: Joi.boolean().optional().default(false),
authorizationParams: Joi.object().optional(),
baseURL: Joi.string().uri().required(),
clientID: Joi.string().required(),
clientSecret: Joi.string().optional(),
clockTolerance: Joi.number().optional().default(60),
errorOnRequiredAuth: Joi.boolean().optional().default(false),
getUser: Joi.func().optional().default(getUser),
handleCallback: Joi.func().optional().default(handleCallback),
httpOptions: Joi.object().optional(),
identityClaimFilter: Joi.array().optional().default(['aud', 'iss', 'iat', 'exp', 'nonce', 'azp', 'auth_time']),
idpLogout: Joi.boolean().optional().default(false).when(
'auth0Logout', { is: true, then: Joi.boolean().optional().default(true) }
),
idTokenAlg: Joi.string().not('none').optional().default('RS256'),
issuerBaseURL: Joi.alternatives([ Joi.string().uri(), Joi.string().hostname() ]).required(),
legacySameSiteCookie: Joi.boolean().optional().default(true),
loginPath: Joi.string().optional().default('/login'),
logoutPath: Joi.string().optional().default('/logout'),
redirectUriPath: Joi.string().optional().default('/callback'),
required: Joi.alternatives([ Joi.func(), Joi.boolean()]).optional().default(true),
routes: Joi.boolean().optional().default(true),
});

function buildAuthorizeParams(authorizationParams) {
Expand Down
22 changes: 1 addition & 21 deletions middleware/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,7 @@ const appSession = require('../lib/appSession');
/**
* Returns a router with two routes /login and /callback
*
* @param {Object} [params] The parameters object
* @param {string} [params.issuerBaseURL] The url address for the token issuer.
* @param {string} [params.baseURL] The url of the web application where you are installing the router.
* @param {string} [params.clientID] The client id.
* @param {string} [params.clientSecret] The client secret, only required for some grants.
* @param {string} [params.clockTolerance] The clock's tolerance in seconds for token verification.
* @param {Function} [params.getUser] An async function receiving a tokenset and returning the profile for req.user.
* @param {boolean|Function} [params.required=true] a boolean to indicate that every route after this middleware requires authentication or
* a function receiving a request and return a boolean to determine which routes needs authentication.
* @param {boolean} [params.errorOnRequiredAuth=false] automatically handle unauthorized errors by triggering the authentication process
* @param {boolean} [params.idpLogout=false] logout the user from the identity provider on logout
* @param {boolean} [params.auth0Logout=false] use the auth0's logout mechanism if OpenID Connect session management is not supported
* @param {boolean|Function} [params.routes=true] a boolean indicating if the routes /login and /logout should be added to the application
* @param {string} [params.redirectUriPath=/callback] The path for the redirect uri, defaults to /callback.
* @param {Object} [params.authorizationParams] The parameters for the authorization call. Defaults to
* - response_type: "id_token"
* - reponse_mode: "form_post"
* - scope: "openid profile email"
* @param {string} params.authorizationParams.response_type The response type.
* @param {string} [params.authorizationParams.response_mode] The response mode.
* @param {string} [params.authorizationParams.scope=openid profile email] The scope.
* @param {Object} [params] The parameters object; see index.d.ts for types and descriptions.
*
* @returns {express.Router} the router
*/
Expand Down