@adonisjs/auth
Version:
Official authentication provider for Adonis framework
182 lines (181 loc) • 5.73 kB
JavaScript
"use strict";
/*
* @adonisjs/auth
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasicAuthGuard = void 0;
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
const Base_1 = require("../Base");
const AuthenticationException_1 = require("../../Exceptions/AuthenticationException");
/**
* RegExp for basic auth credentials.
* Copy/pasted from https://github.com/jshttp/basic-auth/blob/master/index.js
*
* credentials = auth-scheme 1*SP token68
* auth-scheme = "Basic" ; case insensitive
* token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"="
*/
const CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
/**
* RegExp for basic auth user/pass
* Copy/pasted from https://github.com/jshttp/basic-auth/blob/master/index.js
*
* user-pass = userid ":" password
* userid = *<TEXT excluding ":">
* password = *TEXT
*/
const USER_PASS_REGEXP = /^([^:]*):(.*)$/;
/**
* Basic auth guard enables user login using basic auth headers.
*/
class BasicAuthGuard extends Base_1.BaseGuard {
constructor(name, config, emitter, provider, ctx) {
super(name, config, provider);
this.emitter = emitter;
this.ctx = ctx;
}
/**
* Returns data packet for the authenticate event. Arguments are
*
* - The mapping identifier
* - Logged in user
* - HTTP context
*/
getAuthenticateEventData(user) {
return {
name: this.name,
ctx: this.ctx,
user,
};
}
/**
* Returns user credentials by parsing the HTTP "Authorization" header
*/
getCredentials() {
/**
* Ensure the "Authorization" header value exists
*/
const credentials = this.ctx.request.header('Authorization');
if (!credentials) {
throw AuthenticationException_1.AuthenticationException.invalidBasicCredentials(this.name);
}
/**
* Ensure credentials are in correct format
*/
const match = CREDENTIALS_REGEXP.exec(credentials);
if (!match) {
throw AuthenticationException_1.AuthenticationException.invalidBasicCredentials(this.name);
}
/**
* Ensure credentials are base64 encoded
*/
const decoded = helpers_1.base64.decode(match[1], 'utf-8', true);
if (!decoded) {
throw AuthenticationException_1.AuthenticationException.invalidBasicCredentials(this.name);
}
/**
* Ensure decoded credentials are in correct format
*/
const user = USER_PASS_REGEXP.exec(decoded);
if (!user) {
throw AuthenticationException_1.AuthenticationException.invalidBasicCredentials(this.name);
}
return { uid: user[1], password: user[2] };
}
/**
* Returns user for the uid and password.
*/
async getUser(uid, password) {
try {
return await this.verifyCredentials(uid, password);
}
catch {
throw AuthenticationException_1.AuthenticationException.invalidBasicCredentials(this.name);
}
}
/**
* Implemented method to raise exception when someone calls this method
* without selecting the guard explicitly
*/
async attempt() {
return this.login();
}
/**
* Implemented method to raise exception when someone calls this method
* without selecting the guard explicitly
*/
async loginViaId() {
return this.login();
}
/**
* Implemented method to raise exception when someone calls this method
* without selecting the guard explicitly
*/
async login() {
throw new utils_1.Exception('There is no concept of login in basic auth', 500);
}
/**
* Authenticates the current HTTP request by checking for the HTTP
* "Authorization" header
*/
async authenticate() {
if (this.authenticationAttempted) {
return this.user;
}
this.authenticationAttempted = true;
/**
* Parse HTTP "Authorization" header to get credentials
*/
const credentials = this.getCredentials();
/**
* Pull user from credentials
*/
const user = await this.getUser(credentials.uid, credentials.password);
/**
* Mark user a logged in
*/
this.markUserAsLoggedIn(user, true);
/**
* Emit event
*/
this.emitter.emit('adonis:basic:authenticate', this.getAuthenticateEventData(user));
return this.user;
}
/**
* Same as [[authenticate]] but returns a boolean over raising exceptions
*/
async check() {
try {
await this.authenticate();
}
catch (error) {
this.ctx.logger.trace(error, 'Authentication failure');
}
return this.isAuthenticated;
}
/**
* Logout by clearing session and cookies
*/
async logout() {
throw new utils_1.Exception('There is no concept of logout in basic auth', 500);
}
/**
* Serialize toJSON for JSON.stringify
*/
toJSON() {
return {
isLoggedIn: this.isLoggedIn,
isGuest: this.isGuest,
authenticationAttempted: this.authenticationAttempted,
isAuthenticated: this.isAuthenticated,
user: this.user,
};
}
}
exports.BasicAuthGuard = BasicAuthGuard;