This commit is contained in:
thosakwe 2017-04-24 23:02:50 -04:00
parent e4bcd3cb47
commit 54fb98948a
5 changed files with 40 additions and 24 deletions

View file

@ -12,7 +12,7 @@
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="application" />
<orderEntry type="library" name="Dart Packages" level="project" /> <orderEntry type="library" name="Dart Packages" level="project" />
<orderEntry type="library" name="Dart SDK" level="project" />
</component> </component>
</module> </module>

View file

@ -1,6 +1,6 @@
# angel_auth # angel_auth
[![version 1.0.2](https://img.shields.io/badge/version-1.0.2-brightgreen.svg)](https://pub.dartlang.org/packages/angel_auth) [![version 1.0.3](https://img.shields.io/badge/version-1.0.3-brightgreen.svg)](https://pub.dartlang.org/packages/angel_auth)
![build status](https://travis-ci.org/angel-dart/auth.svg?branch=master) ![build status](https://travis-ci.org/angel-dart/auth.svg?branch=master)
A complete authentication plugin for Angel. Inspired by Passport. A complete authentication plugin for Angel. Inspired by Passport.

View file

@ -2,8 +2,29 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:angel_framework/angel_framework.dart'; import 'package:angel_framework/angel_framework.dart';
/// Restricts access to a resource via authentication. Constant instance.
const RequestMiddleware requireAuth = const RequireAuthorizationMiddleware();
/// Forces Basic authentication over the requested resource, with the given [realm] name, if no JWT is present.
///
/// [realm] defaults to `'angel_auth'`.
RequestHandler forceBasicAuth({String realm}) {
return (RequestContext req, ResponseContext res) async {
if (req.properties.containsKey('user')) return true;
res
..statusCode = HttpStatus.UNAUTHORIZED
..headers[HttpHeaders.WWW_AUTHENTICATE] =
'Basic realm="${realm ?? 'angel_auth'}"'
..end();
return false;
};
}
/// Restricts access to a resource via authentication. /// Restricts access to a resource via authentication.
class RequireAuthorizationMiddleware extends AngelMiddleware { class RequireAuthorizationMiddleware implements AngelMiddleware {
const RequireAuthorizationMiddleware();
@override @override
Future<bool> call(RequestContext req, ResponseContext res, Future<bool> call(RequestContext req, ResponseContext res,
{bool throwError: true}) async { {bool throwError: true}) async {

View file

@ -14,8 +14,6 @@ class AngelAuth extends AngelPlugin {
num _jwtLifeSpan; num _jwtLifeSpan;
Math.Random _random = new Math.Random.secure(); Math.Random _random = new Math.Random.secure();
final RegExp _rgxBearer = new RegExp(r"^Bearer"); final RegExp _rgxBearer = new RegExp(r"^Bearer");
RequireAuthorizationMiddleware _requireAuth =
new RequireAuthorizationMiddleware();
final bool allowCookie; final bool allowCookie;
final bool allowTokenInQuery; final bool allowTokenInQuery;
String middlewareName; String middlewareName;
@ -59,13 +57,19 @@ class AngelAuth extends AngelPlugin {
if (runtimeType != AngelAuth) app.container.singleton(this, as: AngelAuth); if (runtimeType != AngelAuth) app.container.singleton(this, as: AngelAuth);
app.before.add(decodeJwt); app.before.add(decodeJwt);
app.registerMiddleware(middlewareName, _requireAuth); app.registerMiddleware(middlewareName, requireAuth);
if (reviveTokenEndpoint != null) { if (reviveTokenEndpoint != null) {
app.post(reviveTokenEndpoint, reviveJwt); app.post(reviveTokenEndpoint, reviveJwt);
} }
} }
void _apply(RequestContext req, AuthToken token, user) {
req
..inject(AuthToken, req.properties['token'] = token)
..inject(user.runtimeType, req.properties["user"] = user);
}
decodeJwt(RequestContext req, ResponseContext res) async { decodeJwt(RequestContext req, ResponseContext res) async {
if (req.method == "POST" && req.path == reviveTokenEndpoint) { if (req.method == "POST" && req.path == reviveTokenEndpoint) {
// Shouldn't block invalid JWT if we are reviving it // Shouldn't block invalid JWT if we are reviving it
@ -119,10 +123,7 @@ class AngelAuth extends AngelPlugin {
} }
final user = await deserializer(token.userId); final user = await deserializer(token.userId);
_apply(req, token, user);
req
..inject(AuthToken, req.properties['token'] = token)
..inject(user.runtimeType, req.properties["user"] = user);
} }
return true; return true;
@ -243,9 +244,7 @@ class AngelAuth extends AngelPlugin {
if (r != null) return r; if (r != null) return r;
} }
req _apply(req, token, result);
..inject(AuthToken, req.properties['token'] = token)
..inject(result.runtimeType, req.properties["user"] = result);
if (allowCookie) res.cookies.add(new Cookie("token", jwt)); if (allowCookie) res.cookies.add(new Cookie("token", jwt));
@ -254,13 +253,15 @@ class AngelAuth extends AngelPlugin {
} }
if (options?.successRedirect?.isNotEmpty == true) { if (options?.successRedirect?.isNotEmpty == true) {
return res.redirect(options.successRedirect, code: HttpStatus.OK); res.redirect(options.successRedirect, code: HttpStatus.OK);
return false;
} else if (options?.canRespondWithJson != false && } else if (options?.canRespondWithJson != false &&
req.headers.value("accept") != null && req.headers.value("accept") != null &&
(req.headers.value("accept").contains("application/json") || (req.headers.value("accept").contains("application/json") ||
req.headers.value("accept").contains("*/*") || req.headers.value("accept").contains("*/*") ||
req.headers.value("accept").contains("application/*"))) { req.headers.value("accept").contains("application/*"))) {
return {"data": result, "token": jwt}; var user = await deserializer(await serializer(result));
return {"data": user, "token": jwt};
} }
return true; return true;
@ -277,10 +278,7 @@ class AngelAuth extends AngelPlugin {
/// Log a user in on-demand. /// Log a user in on-demand.
Future login(AuthToken token, RequestContext req, ResponseContext res) async { Future login(AuthToken token, RequestContext req, ResponseContext res) async {
var user = await deserializer(token.userId); var user = await deserializer(token.userId);
_apply(req, token, user);
req
..inject(AuthToken, req.properties['token'] = token)
..inject(user.runtimeType, req.properties["user"] = user);
if (allowCookie) if (allowCookie)
res.cookies.add(new Cookie('token', token.serialize(_hs256))); res.cookies.add(new Cookie('token', token.serialize(_hs256)));
@ -291,10 +289,7 @@ class AngelAuth extends AngelPlugin {
var user = await deserializer(userId); var user = await deserializer(userId);
var token = new AuthToken( var token = new AuthToken(
userId: userId, lifeSpan: _jwtLifeSpan, ipAddress: req.ip); userId: userId, lifeSpan: _jwtLifeSpan, ipAddress: req.ip);
_apply(req, token, user);
req
..inject(AuthToken, req.properties['token'] = token)
..inject(user.runtimeType, req.properties["user"] = user);
if (allowCookie) if (allowCookie)
res.cookies.add(new Cookie('token', token.serialize(_hs256))); res.cookies.add(new Cookie('token', token.serialize(_hs256)));

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.0.2 version: 1.0.3
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: