oauth2-provider/src/model/model.ts

390 lines
7.9 KiB
TypeScript

import { Request, Response } from 'express';
import { OAuth2Logger } from '../utils/logger';
/**
* OAuth2 client object
*/
export interface OAuth2Client {
id: string | number;
secret: string;
scope: string[];
grants: string[];
}
/**
* OAuth2 access token object
*/
export interface OAuth2AccessToken {
token: string;
user_id: string | number;
client_id: string | number;
scope: string;
expires_at: Date;
}
/**
* OAuth2 authorization code object
*/
export interface OAuth2Code {
code: string;
expires_at: Date;
user_id: string | number;
client_id: string | number;
scope: string;
nonce?: string;
code_challenge_method?: 'plain' | 'S256';
code_challenge?: string;
}
/**
* OAuth2 refresh token object
*/
export interface OAuth2RefreshToken {
token: string;
user_id: string | number;
client_id: string | number;
scope: string;
}
/**
* OAuth2 implicit user model
*/
export interface OAuth2User {
id: string | number;
username: string;
password: string;
}
/**
* OAuth2 token response
*/
export interface OAuth2TokenResponse {
id_token?: string;
access_token?: string;
refresh_token?: string;
expires_in?: number;
token_type?: string;
state?: string;
}
/**
* OAuth2 access token adapter model
*/
export interface OAuth2AccessTokenAdapter {
/**
* Static time-to-live in seconds for access token
*/
ttl: number;
/**
* Get the token string from an access token object
*/
getToken: (token: OAuth2AccessToken) => string;
/**
* Create a new access token
*/
create: (
userId: string | number | null,
clientId: string | number,
scope: string | string[],
ttl: number
) => Promise<string>;
/**
* Fetch an access token by the token string from the database
*/
fetchByToken: (
token: OAuth2AccessToken | string
) => Promise<OAuth2AccessToken>;
/**
* Check the time-to-live value
*/
checkTTL: (token: OAuth2AccessToken) => boolean;
/**
* Get the time-to-live value from a token object
*/
getTTL: (token: OAuth2AccessToken) => number;
/**
* Fetch an access token by user ID and client ID from the database
*/
fetchByUserIdClientId: (
userId: string | number,
clientId: string | number
) => Promise<OAuth2AccessToken>;
}
/**
* OAuth2 client adapter model
*/
export interface OAuth2ClientAdapter {
/**
* Get client ID from client object
*/
getId: (client: OAuth2Client) => string | number;
/**
* Get client object from the database by client ID
*/
fetchById: (id: string | number) => Promise<OAuth2Client>;
/**
* Check the client secret
*/
checkSecret: (client: OAuth2Client, secret: string) => boolean;
/**
* Check grant type
*/
checkGrantType: (client: OAuth2Client, grant: string) => boolean;
/**
* Get the redirect uri of a client
*/
hasRedirectUri: (client: OAuth2Client) => Promise<boolean>;
/**
* Check the redirect uri against a client
*/
checkRedirectUri: (
client: OAuth2Client,
redirectUri: string
) => Promise<boolean>;
/**
* Transform the scope into a string array of scopes
*/
transformScope: (scope: string | string[]) => string[];
/**
* Check scopes against client
*/
checkScope: (client: OAuth2Client, scope: string[]) => boolean;
}
/**
* OAuth2 response code adapter model
*/
export interface OAuth2CodeAdapter {
/**
* Static time-to-live in seconds for code
*/
ttl: number;
/**
* Create a new code
*/
create: (
userId: string | number,
clientId: string | number,
scope: string | string[],
ttl: number,
nonce?: string,
code_challenge?: string,
code_challenge_method?: 'plain' | 'S256',
) => Promise<string>;
/**
* Fetch a code by the code string from the database
*/
fetchByCode: (code: OAuth2Code | string) => Promise<OAuth2Code>;
/**
* Remove a code
*/
removeByCode: (code: string | OAuth2Code) => Promise<boolean>;
/**
* Get user ID from a code object
*/
getUserId: (code: OAuth2Code) => string | number;
/**
* Get client ID from a code object
*/
getClientId: (code: OAuth2Code) => string | number;
/**
* Get scope from a code object
*/
getScope: (code: OAuth2Code) => string;
/**
* Check the time-to-live value
*/
checkTTL: (code: OAuth2Code) => boolean;
/**
* Get PCKE info
*/
getCodeChallenge?: (code: OAuth2Code) => { method: 'plain' | 'S256'; challenge: string; }
}
/**
* OAuth2 refresh token adapter model
*/
export interface OAuth2RefreshTokenAdapter {
/**
* Invalidate all previous refresh tokens for user/client when new one is issued.
*/
invalidateOld: boolean;
/**
* Create a new refresh token
*/
create: (
userId: string | number,
clientId: string | number,
scope: string | string[]
) => Promise<string>;
/**
* Fetch a token from the database
*/
fetchByToken: (
token: OAuth2RefreshToken | string
) => Promise<OAuth2RefreshToken>;
/**
* Remove refresh token by user ID and client ID
*/
removeByUserIdClientId: (
userId: string | number,
clientId: string | number
) => Promise<boolean>;
/**
* Remove token by the token itself
*/
removeByRefreshToken: (token: string) => Promise<boolean>;
/**
* Get user ID from token
*/
getUserId: (token: OAuth2RefreshToken) => string | number;
/**
* Get client ID from token
*/
getClientId: (token: OAuth2RefreshToken) => string | number;
/**
* Get scope from token
*/
getScope: (token: OAuth2RefreshToken) => string;
}
/**
* OAuth2 user adapter model
*/
export interface OAuth2UserAdapter {
/**
* Get user ID
*/
getId: (user: OAuth2User) => string | number;
/**
* Get user from the database by ID
*/
fetchById: (id: string | number) => Promise<OAuth2User>;
/**
* Fetch a user from the database by username
*/
fetchByUsername: (username: string) => Promise<OAuth2User>;
/**
* Check user's password for implicit grant
*/
checkPassword: (user: OAuth2User, password: string) => Promise<boolean>;
/**
* Fetch the user from the express request
*/
fetchFromRequest: (req: Request) => Promise<OAuth2User>;
/**
* Check if the user has already consented to this client and the scopes. Return false to force a decision.
*/
consented: (
userId: string | number,
clientId: string | number,
scope: string | string[]
) => Promise<boolean>;
/**
* Save a consent
*/
consent: (
userId: string | number,
clientId: string | number,
scope: string | string[]
) => Promise<boolean>;
}
/**
* Adapter for managing the `openid` scope.
*/
export interface JWTAdapter {
/**
* Issue a new ID token for user.
* @param user User data object obtained from the User adapter, must implement `OAuth2User` interface.
* @param scope String-list of scopes (usually used to determine the claims)
* @param nonce Cryptographic key passed to the authentication request, *must* be passed along as a claim.
*/
issueIdToken: (
user: OAuth2User,
client: OAuth2Client,
scope: string[],
nonce?: string
) => Promise<string>;
}
/**
* Render the OAuth2 decision page
*/
export type RenderOAuth2Decision = (
req: Request,
res: Response,
client: OAuth2Client,
scope: string[],
user: OAuth2User,
redirectUri: string
) => void;
/**
* OAuth2 adapter model
*/
export interface OAuth2AdapterModel {
accessToken: OAuth2AccessTokenAdapter;
refreshToken: OAuth2RefreshTokenAdapter;
user: OAuth2UserAdapter;
client: OAuth2ClientAdapter;
code: OAuth2CodeAdapter;
jwt?: JWTAdapter;
}
/**
* OAuth2 adapter
*/
export interface OAuth2 {
/**
* Adapter for the OAuth2 data models.
*/
model: OAuth2AdapterModel;
/**
* Logger wrapper, use a logger of your choice by calling `logger.setLogger(...)`.
* To disable, use `logger.setLogLevel('none')`.
*/
logger: OAuth2Logger;
/**
* Render function for the OAuth2 decision page
*/
decision: RenderOAuth2Decision;
}