oauth2-provider/src/controller/token.ts

137 lines
3.5 KiB
TypeScript

import * as tokens from './tokens';
import {
InvalidRequest,
InvalidClient,
UnauthorizedClient,
UnsupportedGrantType,
OAuth2Error,
} from '../model/error';
import {
data as dataResponse,
error as errorResponse,
} from '../utils/response';
import wrap from '../utils/wrap';
import { OAuth2TokenResponse } from '../model/model';
export const token = wrap(async (req, res) => {
let clientId: string | null = null;
let clientSecret: string | null = null;
let grantType: string | null = null;
const { oauth2 } = req;
if (req.body.client_id && req.body.client_secret) {
clientId = req.body.client_id as string;
clientSecret = req.body.client_secret as string;
req.oauth2.logger.debug(
'Client credentials parsed from body parameters',
clientId,
clientSecret
);
} else {
if (!req.headers || !req.headers.authorization) {
throw new InvalidRequest('No authorization header passed');
}
let pieces = req.headers.authorization.split(' ', 2);
if (!pieces || pieces.length !== 2) {
throw new InvalidRequest('Authorization header is corrupted');
}
if (pieces[0] !== 'Basic') {
throw new InvalidRequest(
`Unsupported authorization method: ${pieces[0]}`
);
}
pieces = Buffer.from(pieces[1], 'base64').toString('ascii').split(':', 2);
if (!pieces || pieces.length !== 2) {
throw new InvalidRequest('Authorization header has corrupted data');
}
clientId = pieces[0];
clientSecret = pieces[1];
req.oauth2.logger.debug(
'Client credentials parsed from basic auth header:',
clientId,
clientSecret
);
}
if (!req.body.grant_type) {
throw new InvalidRequest(
'Request body does not contain grant_type parameter'
);
}
grantType = req.body.grant_type as string;
req.oauth2.logger.debug('Parameter grant_type is', grantType);
const client = await oauth2.model.client.fetchById(clientId);
if (!client) {
throw new InvalidClient('Client not found');
}
const valid = oauth2.model.client.checkSecret(client, clientSecret);
if (!valid) {
throw new UnauthorizedClient('Invalid client secret');
}
if (
!oauth2.model.client.checkGrantType(client, grantType) &&
grantType !== 'refresh_token'
) {
throw new UnauthorizedClient('Invalid grant type for the client');
} else {
req.oauth2.logger.debug('Grant type check passed');
}
let tokenResponse: OAuth2TokenResponse;
try {
switch (grantType) {
case 'authorization_code':
tokenResponse = await tokens.authorizationCode(
oauth2,
client,
req.body.code,
req.body.code_verifier
);
break;
case 'password':
tokenResponse = await tokens.password(
oauth2,
client,
req.body.username,
req.body.password,
req.body.scope
);
break;
case 'client_credentials':
tokenResponse = await tokens.clientCredentials(
oauth2,
client,
req.body.scope
);
break;
case 'refresh_token':
tokenResponse = await tokens.refreshToken(
oauth2,
client,
req.body.refresh_token
);
break;
default:
throw new UnsupportedGrantType(
'Grant type does not match any supported type'
);
}
if (tokenResponse) {
dataResponse(req, res, tokenResponse);
}
} catch (e) {
errorResponse(req, res, e as OAuth2Error);
}
});