allow immediate redirect on auth
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Timo Hocker 2021-05-10 12:26:56 +02:00
parent a3f021fdd2
commit e7ad5656e3
4 changed files with 785 additions and 543 deletions

View File

@ -13,6 +13,7 @@ interface AccessSettings {
access_token_expires_in: number access_token_expires_in: number
include_refresh_token?: boolean include_refresh_token?: boolean
refresh_token_expires_in?: number refresh_token_expires_in?: number
redirect_to?: string
data?: Record<string, unknown> data?: Record<string, unknown>
} }
@ -62,9 +63,10 @@ class AuthRequest {
this._cookie_name = cookie; this._cookie_name = cookie;
} }
private default_header () { private default_header (set_content = true) {
this.response.setHeader ('Cache-Control', 'no-store'); this.response.setHeader ('Cache-Control', 'no-store');
this.response.setHeader ('Pragma', 'no-cache'); this.response.setHeader ('Pragma', 'no-cache');
if (set_content)
this.response.setHeader ('Content-Type', 'application/json'); this.response.setHeader ('Content-Type', 'application/json');
} }
@ -72,9 +74,10 @@ class AuthRequest {
access_token_expires_in, access_token_expires_in,
include_refresh_token, include_refresh_token,
refresh_token_expires_in, refresh_token_expires_in,
redirect_to,
data data
}: AccessSettings): Promise<AccessResult> { }: AccessSettings): Promise<AccessResult> {
this.default_header (); this.default_header (typeof redirect_to !== 'string');
const at = await auth.sign ( const at = await auth.sign (
'access_token', 'access_token',
@ -109,6 +112,14 @@ class AuthRequest {
res.refresh_expires_in = refresh_token_expires_in; res.refresh_expires_in = refresh_token_expires_in;
result.refresh_token_id = rt.id; result.refresh_token_id = rt.id;
} }
if (typeof redirect_to === 'string') {
this.response.setHeader ('Location', redirect_to);
this.response.writeHead (302);
this.response.end ();
return result;
}
this.response.writeHead (200); this.response.writeHead (200);
this.response.end (JSON.stringify (res)); this.response.end (JSON.stringify (res));
@ -156,7 +167,7 @@ class AuthRequest {
} }
} }
type AuthRequestHandler = (req: AuthRequest) => void|Promise<void>; type AuthRequestHandler = (req: AuthRequest) => Promise<void> | void;
interface CreateHandlerOptions { interface CreateHandlerOptions {
refresh?: AccessSettings; refresh?: AccessSettings;

View File

@ -1,6 +1,6 @@
{ {
"name": "@sapphirecode/auth-server-helper", "name": "@sapphirecode/auth-server-helper",
"version": "2.0.1", "version": "2.0.2",
"main": "dist/index.js", "main": "dist/index.js",
"author": { "author": {
"name": "Timo Hocker", "name": "Timo Hocker",
@ -14,7 +14,6 @@
"description": "authentication middleware for node http and express", "description": "authentication middleware for node http and express",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@ert78gb/jasmine-ts": "^0.3.1",
"@sapphirecode/eslint-config-ts": "^1.1.27", "@sapphirecode/eslint-config-ts": "^1.1.27",
"@stryker-mutator/core": "^4.3.1", "@stryker-mutator/core": "^4.3.1",
"@stryker-mutator/jasmine-runner": "^4.3.1", "@stryker-mutator/jasmine-runner": "^4.3.1",
@ -22,6 +21,7 @@
"@types/node": "^10.0.0", "@types/node": "^10.0.0",
"eslint": "^7.14.0", "eslint": "^7.14.0",
"jasmine": "^3.6.3", "jasmine": "^3.6.3",
"jasmine-ts": "^0.3.3",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.1.2" "typescript": "^4.1.2"

View File

@ -36,7 +36,7 @@ function check_headers (resp: Response): CheckHeaderResult {
return { data, at, rt }; return { data, at, rt };
} }
function check_token (token: string, type: string):void { function check_token (token: string, type: string): void {
const v = auth.verify (token); const v = auth.verify (token);
expect (v.valid) expect (v.valid)
.toEqual (true); .toEqual (true);
@ -88,6 +88,12 @@ describe ('auth handler', () => {
else if (req.user === 'part' && req.password === 'bar') { else if (req.user === 'part' && req.password === 'bar') {
req.allow_part (part_expires_seconds, 'two_factor'); req.allow_part (part_expires_seconds, 'two_factor');
} }
else if (req.user === 'red' && req.password === 'irect') {
req.allow_access ({
access_token_expires_in: expires_seconds,
redirect_to: '/redirected'
});
}
else { else {
req.deny (); req.deny ();
} }
@ -290,6 +296,20 @@ describe ('auth handler', () => {
expect (res2.rt).not.toEqual (res1.rt); expect (res2.rt).not.toEqual (res1.rt);
}); });
it ('should do immediate redirect', async () => {
const resp1 = await get ({ authorization: 'Basic red:irect' });
expect (resp1.statusCode)
.toEqual (302);
expect (resp1.headers.location)
.toEqual ('/redirected');
let signature = '';
for (const c of resp1.headers['set-cookie'] as string[]) {
if (c.includes ('cookie_jar='))
signature = c.replace ('cookie_jar=', '');
}
check_token (signature, 'access_token');
});
it ('should handle any authorization type', async () => { it ('should handle any authorization type', async () => {
const resp = await get ({ authorization: 'Foo asdefg' }); const resp = await get ({ authorization: 'Foo asdefg' });
expect (resp.statusCode) expect (resp.statusCode)

1281
yarn.lock

File diff suppressed because it is too large Load Diff