oauth2-provider/src/controller/token.ts

99 lines
3.1 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;
console.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];
console.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;
console.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 {
console.debug('Grant type check passed');
}
let tokenResponse: OAuth2TokenResponse;
try {
switch (grantType) {
case 'authorization_code':
tokenResponse = await tokens.authorizationCode(oauth2, client, req.body.code);
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);
}
})