requireAuth -> requireAuthentication
This commit is contained in:
parent
9fcfcb6f01
commit
f3c5b7988a
13 changed files with 56 additions and 48 deletions
1
.dart_tool/pub/bin/sdk-version
Normal file
1
.dart_tool/pub/bin/sdk-version
Normal file
|
@ -0,0 +1 @@
|
||||||
|
2.0.0-dev.68.0
|
BIN
.dart_tool/pub/bin/test/test.dart.snapshot.dart2
Normal file
BIN
.dart_tool/pub/bin/test/test.dart.snapshot.dart2
Normal file
Binary file not shown.
|
@ -1,3 +1,9 @@
|
||||||
|
# 1.2.0
|
||||||
|
* Deprecate `requireAuth`, in favor of `requireAuthentication`.
|
||||||
|
* Allow configuring of the `userKey`.
|
||||||
|
* Add `authenticateAndContinue`.
|
||||||
|
* Deprecate `middlewareName`.
|
||||||
|
|
||||||
# 1.1.1+6
|
# 1.1.1+6
|
||||||
* Fix a small logic bug that prevented `LocalAuthStrategy`
|
* Fix a small logic bug that prevented `LocalAuthStrategy`
|
||||||
from correctly propagating the authenticated user when
|
from correctly propagating the authenticated user when
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:io';
|
|
||||||
import 'package:angel_framework/angel_framework.dart';
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
|
|
||||||
/// Forces Basic authentication over the requested resource, with the given [realm] name, if no JWT is present.
|
/// Forces Basic authentication over the requested resource, with the given [realm] name, if no JWT is present.
|
||||||
|
@ -10,27 +8,32 @@ RequestHandler forceBasicAuth({String realm}) {
|
||||||
if (req.properties.containsKey('user')) return true;
|
if (req.properties.containsKey('user')) return true;
|
||||||
|
|
||||||
res
|
res
|
||||||
..statusCode = HttpStatus.UNAUTHORIZED
|
..statusCode = 401
|
||||||
..headers[HttpHeaders.WWW_AUTHENTICATE] =
|
..headers['www-authenticate'] = 'Basic realm="${realm ?? 'angel_auth'}"'
|
||||||
'Basic realm="${realm ?? 'angel_auth'}"'
|
|
||||||
..end();
|
..end();
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restricts access to a resource via authentication.
|
/// Use [requireAuthentication] instead.
|
||||||
Future<bool> requireAuth(RequestContext req, ResponseContext res,
|
@deprecated
|
||||||
{bool throwError: true}) async {
|
final RequestMiddleware requireAuth = requireAuthentication(userKey: 'user');
|
||||||
bool _reject(ResponseContext res) {
|
|
||||||
if (throwError) {
|
|
||||||
res.statusCode = HttpStatus.FORBIDDEN;
|
|
||||||
throw new AngelHttpException.forbidden();
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.properties.containsKey('user') || req.method == 'OPTIONS')
|
/// Restricts access to a resource via authentication.
|
||||||
return true;
|
RequestMiddleware requireAuthentication({String userKey: 'user'}) {
|
||||||
else
|
return (RequestContext req, ResponseContext res,
|
||||||
return _reject(res);
|
{bool throwError: true}) async {
|
||||||
|
bool _reject(ResponseContext res) {
|
||||||
|
if (throwError) {
|
||||||
|
res.statusCode = 403;
|
||||||
|
throw new AngelHttpException.forbidden();
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.properties.containsKey(userKey) || req.method == 'OPTIONS')
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return _reject(res);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,8 @@ class AngelAuth<T> {
|
||||||
/// Only applies if [allowCookie] is `true`.
|
/// Only applies if [allowCookie] is `true`.
|
||||||
final String cookiePath;
|
final String cookiePath;
|
||||||
|
|
||||||
/// The name to register [requireAuth] as. Default: `auth`.
|
/// The name to register [requireAuthentication] as. Default: `auth`.
|
||||||
|
@deprecated
|
||||||
String middlewareName;
|
String middlewareName;
|
||||||
|
|
||||||
/// If `true` (default), then JWT's will be considered invalid if used from a different IP than the first user's it was issued to.
|
/// If `true` (default), then JWT's will be considered invalid if used from a different IP than the first user's it was issued to.
|
||||||
|
@ -104,7 +105,8 @@ class AngelAuth<T> {
|
||||||
app.container.singleton(this);
|
app.container.singleton(this);
|
||||||
if (runtimeType != AngelAuth) app.container.singleton(this, as: AngelAuth);
|
if (runtimeType != AngelAuth) app.container.singleton(this, as: AngelAuth);
|
||||||
|
|
||||||
app.registerMiddleware(middlewareName, requireAuth);
|
// ignore: deprecated_member_use
|
||||||
|
app.registerMiddleware(middlewareName, requireAuthentication());
|
||||||
|
|
||||||
if (reviveTokenEndpoint != null) {
|
if (reviveTokenEndpoint != null) {
|
||||||
app.post(reviveTokenEndpoint, reviveJwt);
|
app.post(reviveTokenEndpoint, reviveJwt);
|
||||||
|
@ -189,9 +191,7 @@ class AngelAuth<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_jwtLifeSpan > 0) {
|
if (_jwtLifeSpan > 0) {
|
||||||
cookie.maxAge ??= _jwtLifeSpan < 0
|
cookie.maxAge ??= _jwtLifeSpan < 0 ? -1 : _jwtLifeSpan ~/ 1000;
|
||||||
? -1
|
|
||||||
: _jwtLifeSpan ~/ 1000;
|
|
||||||
cookie.expires ??=
|
cookie.expires ??=
|
||||||
new DateTime.now().add(new Duration(milliseconds: _jwtLifeSpan));
|
new DateTime.now().add(new Duration(milliseconds: _jwtLifeSpan));
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ class AngelAuth<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options?.successRedirect?.isNotEmpty == true) {
|
if (options?.successRedirect?.isNotEmpty == true) {
|
||||||
res.redirect(options.successRedirect, code: HttpStatus.OK);
|
res.redirect(options.successRedirect, code: 200);
|
||||||
return false;
|
return false;
|
||||||
} else if (options?.canRespondWithJson != false &&
|
} else if (options?.canRespondWithJson != false &&
|
||||||
req.accepts('application/json')) {
|
req.accepts('application/json')) {
|
||||||
|
@ -325,7 +325,7 @@ class AngelAuth<T> {
|
||||||
// Check if not redirect
|
// Check if not redirect
|
||||||
if (res.statusCode == 301 ||
|
if (res.statusCode == 301 ||
|
||||||
res.statusCode == 302 ||
|
res.statusCode == 302 ||
|
||||||
res.headers.containsKey(HttpHeaders.LOCATION))
|
res.headers.containsKey('location'))
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
throw new AngelHttpException.notAuthenticated();
|
throw new AngelHttpException.notAuthenticated();
|
||||||
|
|
|
@ -6,7 +6,7 @@ import 'options.dart';
|
||||||
AngelAuthCallback confirmPopupAuthentication({String eventName: 'token'}) {
|
AngelAuthCallback confirmPopupAuthentication({String eventName: 'token'}) {
|
||||||
return (req, ResponseContext res, String jwt) async {
|
return (req, ResponseContext res, String jwt) async {
|
||||||
res
|
res
|
||||||
..contentType = ContentType.HTML
|
..contentType = new ContentType('text', 'html')
|
||||||
..write('''
|
..write('''
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:dart2_constant/convert.dart';
|
import 'package:dart2_constant/convert.dart';
|
||||||
import 'dart:io';
|
|
||||||
import 'package:angel_framework/angel_framework.dart';
|
import 'package:angel_framework/angel_framework.dart';
|
||||||
import '../options.dart';
|
import '../options.dart';
|
||||||
import '../strategy.dart';
|
import '../strategy.dart';
|
||||||
|
@ -45,7 +44,7 @@ class LocalAuthStrategy extends AuthStrategy {
|
||||||
var verificationResult;
|
var verificationResult;
|
||||||
|
|
||||||
if (allowBasic) {
|
if (allowBasic) {
|
||||||
String authHeader = req.headers.value(HttpHeaders.AUTHORIZATION) ?? "";
|
String authHeader = req.headers.value('authorization') ?? "";
|
||||||
|
|
||||||
if (_rgxBasic.hasMatch(authHeader)) {
|
if (_rgxBasic.hasMatch(authHeader)) {
|
||||||
String base64AuthString = _rgxBasic.firstMatch(authHeader).group(1);
|
String base64AuthString = _rgxBasic.firstMatch(authHeader).group(1);
|
||||||
|
@ -82,14 +81,14 @@ class LocalAuthStrategy extends AuthStrategy {
|
||||||
if (verificationResult == false || verificationResult == null) {
|
if (verificationResult == false || verificationResult == null) {
|
||||||
if (options.failureRedirect != null &&
|
if (options.failureRedirect != null &&
|
||||||
options.failureRedirect.isNotEmpty) {
|
options.failureRedirect.isNotEmpty) {
|
||||||
res.redirect(options.failureRedirect, code: HttpStatus.UNAUTHORIZED);
|
res.redirect(options.failureRedirect, code: 401);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forceBasic) {
|
if (forceBasic) {
|
||||||
res
|
res
|
||||||
..statusCode = 401
|
..statusCode = 401
|
||||||
..headers[HttpHeaders.WWW_AUTHENTICATE] = 'Basic realm="$realm"'
|
..headers['www-authenticate'] = 'Basic realm="$realm"'
|
||||||
..end();
|
..end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ abstract class AuthStrategy {
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
/// Authenticates or rejects an incoming user.
|
/// Authenticates or rejects an incoming user.
|
||||||
Future authenticate(RequestContext req, ResponseContext res, [AngelAuthOptions options]);
|
Future authenticate(RequestContext req, ResponseContext res,
|
||||||
|
[AngelAuthOptions options]);
|
||||||
|
|
||||||
/// Determines whether a signed-in user can log out or not.
|
/// Determines whether a signed-in user can log out or not.
|
||||||
Future<bool> canLogout(RequestContext req, ResponseContext res);
|
Future<bool> canLogout(RequestContext req, ResponseContext res);
|
||||||
|
|
|
@ -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+6
|
version: 1.2.0
|
||||||
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:
|
||||||
|
|
|
@ -7,7 +7,7 @@ import 'package:http/http.dart' as http;
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
final AngelAuth auth = new AngelAuth();
|
final AngelAuth auth = new AngelAuth();
|
||||||
var headers = <String, String>{HttpHeaders.ACCEPT: ContentType.JSON.mimeType};
|
var headers = <String, String>{'accept': 'application/json'};
|
||||||
AngelAuthOptions localOpts = new AngelAuthOptions(
|
AngelAuthOptions localOpts = new AngelAuthOptions(
|
||||||
failureRedirect: '/failure', successRedirect: '/success');
|
failureRedirect: '/failure', successRedirect: '/success');
|
||||||
Map sampleUser = {'hello': 'world'};
|
Map sampleUser = {'hello': 'world'};
|
||||||
|
@ -46,8 +46,7 @@ main() async {
|
||||||
app.get('/success', "yep", middleware: ['auth']);
|
app.get('/success', "yep", middleware: ['auth']);
|
||||||
app.get('/failure', "nope");
|
app.get('/failure', "nope");
|
||||||
|
|
||||||
HttpServer server =
|
HttpServer server = await angelHttp.startServer('127.0.0.1', 0);
|
||||||
await angelHttp.startServer('127.0.0.1', 0);
|
|
||||||
url = "http://${server.address.host}:${server.port}";
|
url = "http://${server.address.host}:${server.port}";
|
||||||
basicAuthUrl =
|
basicAuthUrl =
|
||||||
"http://username:password@${server.address.host}:${server.port}";
|
"http://username:password@${server.address.host}:${server.port}";
|
||||||
|
@ -71,25 +70,25 @@ main() async {
|
||||||
Map postData = {'username': 'username', 'password': 'password'};
|
Map postData = {'username': 'username', 'password': 'password'};
|
||||||
var response = await client.post("$url/login",
|
var response = await client.post("$url/login",
|
||||||
body: json.encode(postData),
|
body: json.encode(postData),
|
||||||
headers: {HttpHeaders.CONTENT_TYPE: ContentType.JSON.mimeType});
|
headers: {'content-type': 'application/json'});
|
||||||
expect(response.statusCode, equals(200));
|
expect(response.statusCode, equals(200));
|
||||||
expect(response.headers[HttpHeaders.LOCATION], equals('/success'));
|
expect(response.headers['location'], equals('/success'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('failureRedirect', () async {
|
test('failureRedirect', () async {
|
||||||
Map postData = {'username': 'password', 'password': 'username'};
|
Map postData = {'username': 'password', 'password': 'username'};
|
||||||
var response = await client.post("$url/login",
|
var response = await client.post("$url/login",
|
||||||
body: json.encode(postData),
|
body: json.encode(postData),
|
||||||
headers: {HttpHeaders.CONTENT_TYPE: ContentType.JSON.mimeType});
|
headers: {'content-type': 'application/json'});
|
||||||
print("Login response: ${response.body}");
|
print("Login response: ${response.body}");
|
||||||
expect(response.headers[HttpHeaders.LOCATION], equals('/failure'));
|
expect(response.headers['location'], equals('/failure'));
|
||||||
expect(response.statusCode, equals(401));
|
expect(response.statusCode, equals(401));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('allow basic', () async {
|
test('allow basic', () async {
|
||||||
String authString = base64.encode("username:password".runes.toList());
|
String authString = base64.encode("username:password".runes.toList());
|
||||||
var response = await client.get("$url/hello",
|
var response = await client
|
||||||
headers: {HttpHeaders.AUTHORIZATION: 'Basic $authString'});
|
.get("$url/hello", headers: {'authorization': 'Basic $authString'});
|
||||||
expect(response.body, equals('"Woo auth"'));
|
expect(response.body, equals('"Woo auth"'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -104,7 +103,6 @@ main() async {
|
||||||
.add(new LocalAuthStrategy(verifier, forceBasic: true, realm: 'test'));
|
.add(new LocalAuthStrategy(verifier, forceBasic: true, realm: 'test'));
|
||||||
var response = await client.get("$url/hello", headers: headers);
|
var response = await client.get("$url/hello", headers: headers);
|
||||||
print(response.headers);
|
print(response.headers);
|
||||||
expect(response.headers[HttpHeaders.WWW_AUTHENTICATE],
|
expect(response.headers['www-authenticate'], equals('Basic realm="test"'));
|
||||||
equals('Basic realm="test"'));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue