This commit is contained in:
Tobe O 2018-06-27 14:10:56 -04:00
parent d95c89daae
commit e6403375b4
4 changed files with 36 additions and 18 deletions

View file

@ -1,3 +1,7 @@
# 1.1.1+5
* Prevent duplication of cookies.
* Regenerate the JWT if `tokenCallback` is called.
# 1.1.1+4 # 1.1.1+4
* Patched `logout` to properly erase cookies * Patched `logout` to properly erase cookies
* Fixed checking of expired tokens. * Fixed checking of expired tokens.

View file

@ -30,9 +30,14 @@ class AngelAuth<T> {
/// A domain to restrict emitted cookies to. /// A domain to restrict emitted cookies to.
/// ///
/// Only applies if [secureCookies] is `true`. /// Only applies if [allowCookie] is `true`.
final String cookieDomain; final String cookieDomain;
/// A path to restrict emitted cookies to.
///
/// Only applies if [allowCookie] is `true`.
final String cookiePath;
/// The name to register [requireAuth] as. Default: `auth`. /// The name to register [requireAuth] as. Default: `auth`.
String middlewareName; String middlewareName;
@ -79,6 +84,7 @@ class AngelAuth<T> {
this.allowTokenInQuery: true, this.allowTokenInQuery: true,
this.enforceIp: true, this.enforceIp: true,
this.cookieDomain, this.cookieDomain,
this.cookiePath: '/',
this.secureCookies: true, this.secureCookies: true,
this.middlewareName: 'auth', this.middlewareName: 'auth',
this.reviveTokenEndpoint: "/auth/token"}) this.reviveTokenEndpoint: "/auth/token"})
@ -115,8 +121,7 @@ class AngelAuth<T> {
..inject(user.runtimeType, req.properties["user"] = user); ..inject(user.runtimeType, req.properties["user"] = user);
if (allowCookie == true) { if (allowCookie == true) {
res.cookies _addProtectedCookie(res, 'token', token.serialize(_hs256));
.add(protectCookie(new Cookie('token', token.serialize(_hs256))));
} }
} }
@ -170,12 +175,17 @@ class AngelAuth<T> {
return null; return null;
} }
void _addProtectedCookie(ResponseContext res, String name, String value) {
if (!res.cookies.any((c) => c.name == name)) {
res.cookies.add(protectCookie(new Cookie(name, value)));
}
}
/// Applies security protections to a [cookie]. /// Applies security protections to a [cookie].
Cookie protectCookie(Cookie cookie) { Cookie protectCookie(Cookie cookie) {
if (secureCookies != false) { if (secureCookies != false) {
cookie.httpOnly = true; cookie.httpOnly = true;
cookie.secure = true; cookie.secure = true;
cookie.domain ??= cookieDomain;
} }
if (_jwtLifeSpan > 0) { if (_jwtLifeSpan > 0) {
@ -186,6 +196,8 @@ class AngelAuth<T> {
new DateTime.now().add(new Duration(milliseconds: _jwtLifeSpan)); new DateTime.now().add(new Duration(milliseconds: _jwtLifeSpan));
} }
cookie.domain ??= cookieDomain;
cookie.path ??= cookiePath;
return cookie; return cookie;
} }
@ -221,9 +233,9 @@ class AngelAuth<T> {
} }
} }
if (allowCookie) if (allowCookie) {
res.cookies _addProtectedCookie(res, 'token', token.serialize(_hs256));
.add(protectCookie(new Cookie('token', token.serialize(_hs256)))); }
final data = await deserializer(token.userId); final data = await deserializer(token.userId);
return {'data': data, 'token': token.serialize(_hs256)}; return {'data': data, 'token': token.serialize(_hs256)};
@ -282,12 +294,14 @@ class AngelAuth<T> {
var r = await options.tokenCallback( var r = await options.tokenCallback(
req, res, token, req.properties["user"] = result); req, res, token, req.properties["user"] = result);
if (r != null) return r; if (r != null) return r;
jwt = token.serialize(_hs256);
} }
_apply(req, res, token, result); _apply(req, res, token, result);
if (allowCookie) if (allowCookie) {
res.cookies.add(protectCookie(new Cookie("token", jwt))); _addProtectedCookie(res, 'token', jwt);
}
if (options?.callback != null) { if (options?.callback != null) {
return await options.callback(req, res, jwt); return await options.callback(req, res, jwt);
@ -326,9 +340,9 @@ class AngelAuth<T> {
_apply(req, res, token, user); _apply(req, res, token, user);
_onLogin.add(user); _onLogin.add(user);
if (allowCookie) if (allowCookie) {
res.cookies _addProtectedCookie(res, 'token', token.serialize(_hs256));
.add(protectCookie(new Cookie('token', token.serialize(_hs256)))); }
} }
/// Log a user in on-demand. /// Log a user in on-demand.
@ -339,9 +353,9 @@ class AngelAuth<T> {
_apply(req, res, token, user); _apply(req, res, token, user);
_onLogin.add(user); _onLogin.add(user);
if (allowCookie) if (allowCookie) {
res.cookies _addProtectedCookie(res, 'token', token.serialize(_hs256));
.add(protectCookie(new Cookie('token', token.serialize(_hs256)))); }
} }
/// Log an authenticated user out. /// Log an authenticated user out.
@ -367,7 +381,7 @@ class AngelAuth<T> {
if (allowCookie == true) { if (allowCookie == true) {
res.cookies.removeWhere((cookie) => cookie.name == "token"); res.cookies.removeWhere((cookie) => cookie.name == "token");
res.cookies.add(protectCookie(new Cookie('token', ''))); _addProtectedCookie(res, 'token', '');
} }
if (options != null && if (options != null &&

View file

@ -1,6 +1,6 @@
name: angel_auth name: angel_auth
description: A complete authentication plugin for Angel. description: A complete authentication plugin for Angel.
version: 1.1.1+4 version: 1.1.1+5
author: Tobe O <thosakwe@gmail.com> author: Tobe O <thosakwe@gmail.com>
homepage: https://github.com/angel-dart/angel_auth homepage: https://github.com/angel-dart/angel_auth
environment: environment:

View file

@ -25,7 +25,7 @@ main() {
angelHttp = new AngelHttp(app, useZone: false); angelHttp = new AngelHttp(app, useZone: false);
app.use('/users', new TypedService<User>(new MapService())); app.use('/users', new TypedService<User>(new MapService()));
User jdoe = await app await app
.service('users') .service('users')
.create({'username': 'jdoe1', 'password': 'password'}); .create({'username': 'jdoe1', 'password': 'password'});