|
@@ -9,21 +9,44 @@ import type { AccessTokenParserReq } from './interfaces';
|
|
|
|
|
|
|
|
const logger = loggerFactory('growi:middleware:access-token-parser');
|
|
const logger = loggerFactory('growi:middleware:access-token-parser');
|
|
|
|
|
|
|
|
|
|
+export const extractBearerToken = (authHeader: string | undefined): string | null => {
|
|
|
|
|
+ if (authHeader == null) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!authHeader.startsWith('Bearer ')) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return authHeader.substring(7); // Remove 'Bearer ' prefix
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
export type AccessTokenParser = (scopes?: Scope[], opts?: {acceptLegacy: boolean})
|
|
export type AccessTokenParser = (scopes?: Scope[], opts?: {acceptLegacy: boolean})
|
|
|
=> (req: AccessTokenParserReq, res: Response, next: NextFunction) => Promise<void>
|
|
=> (req: AccessTokenParserReq, res: Response, next: NextFunction) => Promise<void>
|
|
|
|
|
|
|
|
export const accessTokenParser: AccessTokenParser = (scopes, opts) => {
|
|
export const accessTokenParser: AccessTokenParser = (scopes, opts) => {
|
|
|
return async(req, res, next): Promise<void> => {
|
|
return async(req, res, next): Promise<void> => {
|
|
|
- // TODO: comply HTTP header of RFC6750 / Authorization: Bearer
|
|
|
|
|
|
|
+ // Extract token from Authorization header first
|
|
|
|
|
+ const bearerToken = extractBearerToken(req.headers.authorization);
|
|
|
|
|
+
|
|
|
|
|
+ // Try all possible token sources in order of priority
|
|
|
|
|
+ const accessToken = bearerToken ?? req.query.access_token ?? req.body.access_token;
|
|
|
|
|
+ if (accessToken == null || typeof accessToken !== 'string') {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ logger.debug('accessToken is', accessToken);
|
|
|
|
|
+
|
|
|
if (scopes == null || scopes.length === 0) {
|
|
if (scopes == null || scopes.length === 0) {
|
|
|
logger.warn('scopes is empty');
|
|
logger.warn('scopes is empty');
|
|
|
return next();
|
|
return next();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- await parserForAccessToken(scopes)(req, res);
|
|
|
|
|
|
|
+ await parserForAccessToken(accessToken, scopes)(req, res);
|
|
|
|
|
|
|
|
if (opts?.acceptLegacy) {
|
|
if (opts?.acceptLegacy) {
|
|
|
- await parserForApiToken(req, res);
|
|
|
|
|
|
|
+ await parserForApiToken(accessToken)(req, res);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return next();
|
|
return next();
|