Update auth
This commit is contained in:
parent
62336e0d53
commit
fdc909b536
7 changed files with 41 additions and 40 deletions
|
@ -20,7 +20,7 @@
|
||||||
* Migrated angel_validate to 4.0.0 (7/7 tests passed)
|
* Migrated angel_validate to 4.0.0 (7/7 tests passed)
|
||||||
* Migrated json_god to 4.0.0 (13/13 tests passed)
|
* Migrated json_god to 4.0.0 (13/13 tests passed)
|
||||||
* Migrated angel_client to 4.0.0 (13/13 tests passed)
|
* Migrated angel_client to 4.0.0 (13/13 tests passed)
|
||||||
* Migrated angel_websocket to 4.0.0 (2/3 tests passed)
|
* Migrated angel_websocket to 4.0.0 (3/3 tests passed)
|
||||||
* Migrated angel_test to 4.0.0 (1/1 test passed)
|
* Migrated angel_test to 4.0.0 (1/1 test passed)
|
||||||
* Added symbol_table and migrated to 2.0.0 (16/16 tests passed)
|
* Added symbol_table and migrated to 2.0.0 (16/16 tests passed)
|
||||||
* Migrated jael to 4.0.0 (20/20 tests passed)
|
* Migrated jael to 4.0.0 (20/20 tests passed)
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
|
## 4.0.5
|
||||||
|
|
||||||
|
* Added support for verifier function to return an empty Map instead of null
|
||||||
|
* Fixed `canRespondWithJson` option to return data in the reponse body when set to true
|
||||||
|
|
||||||
## 4.0.4
|
## 4.0.4
|
||||||
|
|
||||||
* Changed `serializer` and `deserializer` parameters to be required
|
* Changed `serializer` and `deserializer` parameters to be required
|
||||||
* Fixed HTTP basic authentication
|
* Fixed HTTP basic authentication
|
||||||
* Passed all 51 unit tests
|
* All 31 unit tests passed
|
||||||
|
|
||||||
## 4.0.3
|
## 4.0.3
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Angel3 Anthentication
|
# Angel3 Anthentication
|
||||||
|
|
||||||
[![version](https://img.shields.io/badge/pub-v4.0.4-brightgreen)](https://pub.dev/packages/angel3_auth)
|
[![version](https://img.shields.io/badge/pub-v4.0.5-brightgreen)](https://pub.dev/packages/angel3_auth)
|
||||||
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
[![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety)
|
||||||
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
[![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion)
|
||||||
|
|
||||||
|
@ -52,9 +52,7 @@ configureServer(Angel app) async {
|
||||||
|
|
||||||
## Default Authentication Callback
|
## Default Authentication Callback
|
||||||
|
|
||||||
A frequent use case within SPA's is opening OAuth login endpoints in a separate window.
|
A frequent use case within SPA's is opening OAuth login endpoints in a separate window. [`angel3_client`](https://github.com/dukefirehawk/angel/tree/angel3/packages/client) provides a facility for this, which works perfectly with the default callback provided in this package.
|
||||||
[`angel3_client`](https://github.com/dukefirehawk/angel/tree/angel3/packages/client)
|
|
||||||
provides a facility for this, which works perfectly with the default callback provided in this package.
|
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
configureServer(Angel app) async {
|
configureServer(Angel app) async {
|
||||||
|
@ -77,8 +75,7 @@ configureServer(Angel app) async {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This renders a simple HTML page that fires the user's JWT as a `token` event in `window.opener`.
|
This renders a simple HTML page that fires the user's JWT as a `token` event in `window.opener`. `angel3_client` [exposes this as a Stream](https://github.com/dukefirehawk/angel/tree/angel3/packages/client#authentication):
|
||||||
`angel3_client` [exposes this as a Stream](https://github.com/dukefirehawk/angel/tree/angel3/packages/client#authentication):
|
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
app.authenticateViaPopup('/auth/google').listen((jwt) {
|
app.authenticateViaPopup('/auth/google').listen((jwt) {
|
||||||
|
|
|
@ -352,9 +352,12 @@ class AngelAuth<User> {
|
||||||
/// or a `401 Not Authenticated` is thrown, if it is the last one.
|
/// or a `401 Not Authenticated` is thrown, if it is the last one.
|
||||||
///
|
///
|
||||||
/// Any other result is considered an authenticated user, and terminates the loop.
|
/// Any other result is considered an authenticated user, and terminates the loop.
|
||||||
RequestHandler authenticate(type, [AngelAuthOptions<User>? options]) {
|
RequestHandler authenticate(type, [AngelAuthOptions<User>? opt]) {
|
||||||
return (RequestContext req, ResponseContext res) async {
|
return (RequestContext req, ResponseContext res) async {
|
||||||
|
var authOption = opt ?? AngelAuthOptions<User>();
|
||||||
|
|
||||||
var names = <String>[];
|
var names = <String>[];
|
||||||
|
|
||||||
var arr = type is Iterable
|
var arr = type is Iterable
|
||||||
? type.map((x) => x.toString()).toList()
|
? type.map((x) => x.toString()).toList()
|
||||||
: [type.toString()];
|
: [type.toString()];
|
||||||
|
@ -386,11 +389,12 @@ class AngelAuth<User> {
|
||||||
var hasExisting = reqContainer?.has<User>() ?? false;
|
var hasExisting = reqContainer?.has<User>() ?? false;
|
||||||
var result = hasExisting
|
var result = hasExisting
|
||||||
? reqContainer?.make<User>()
|
? reqContainer?.make<User>()
|
||||||
: await strategy.authenticate(req, res, options);
|
: await strategy.authenticate(req, res, authOption);
|
||||||
|
|
||||||
if (result != null && result == true) {
|
if (result == true) {
|
||||||
return result;
|
return result;
|
||||||
} else if (result != false && result != null) {
|
} else if (result != null && result != false) {
|
||||||
|
//} else if (result != null && result is Map && result.isNotEmpty) {
|
||||||
var userId = await serializer(result);
|
var userId = await serializer(result);
|
||||||
|
|
||||||
// Create JWT
|
// Create JWT
|
||||||
|
@ -398,13 +402,13 @@ class AngelAuth<User> {
|
||||||
userId: userId, lifeSpan: _jwtLifeSpan, ipAddress: req.ip);
|
userId: userId, lifeSpan: _jwtLifeSpan, ipAddress: req.ip);
|
||||||
var jwt = token.serialize(_hs256);
|
var jwt = token.serialize(_hs256);
|
||||||
|
|
||||||
if (options != null && options.tokenCallback != null) {
|
if (authOption.tokenCallback != null) {
|
||||||
var hasUser = reqContainer?.has<User>() ?? false;
|
var hasUser = reqContainer?.has<User>() ?? false;
|
||||||
if (!hasUser) {
|
if (!hasUser) {
|
||||||
reqContainer?.registerSingleton<User>(result);
|
reqContainer?.registerSingleton<User>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
var r = await options.tokenCallback!(req, res, token, result);
|
var r = await authOption.tokenCallback!(req, res, token, result);
|
||||||
if (r != null) return r;
|
if (r != null) return r;
|
||||||
jwt = token.serialize(_hs256);
|
jwt = token.serialize(_hs256);
|
||||||
}
|
}
|
||||||
|
@ -416,24 +420,15 @@ class AngelAuth<User> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options is not null
|
// Options is not null
|
||||||
if (options != null) {
|
if (authOption.callback != null) {
|
||||||
if (options.callback != null) {
|
return await authOption.callback!(req, res, jwt);
|
||||||
return await options.callback!(req, res, jwt);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (options.successRedirect?.isNotEmpty == true) {
|
if (authOption.successRedirect?.isNotEmpty == true) {
|
||||||
await res.redirect(options.successRedirect);
|
await res.redirect(authOption.successRedirect);
|
||||||
return false;
|
return false;
|
||||||
} else if (options.canRespondWithJson &&
|
} else if (authOption.canRespondWithJson &&
|
||||||
req.accepts('application/json')) {
|
req.accepts('application/json')) {
|
||||||
var user = hasExisting
|
|
||||||
? result
|
|
||||||
: await deserializer((await serializer(result)) as Object);
|
|
||||||
_onLogin.add(user);
|
|
||||||
return {'data': user, 'token': jwt};
|
|
||||||
}
|
|
||||||
// Options is null
|
|
||||||
} else if (hasExisting && req.accepts('application/json')) {
|
|
||||||
var user = hasExisting
|
var user = hasExisting
|
||||||
? result
|
? result
|
||||||
: await deserializer((await serializer(result)) as Object);
|
: await deserializer((await serializer(result)) as Object);
|
||||||
|
@ -449,8 +444,8 @@ class AngelAuth<User> {
|
||||||
res.statusCode == 302 ||
|
res.statusCode == 302 ||
|
||||||
res.headers.containsKey('location')) {
|
res.headers.containsKey('location')) {
|
||||||
return false;
|
return false;
|
||||||
} else if (options != null && options.failureRedirect != null) {
|
} else if (authOption.failureRedirect != null) {
|
||||||
await res.redirect(options.failureRedirect);
|
await res.redirect(authOption.failureRedirect);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
_log.warning('Not authenticated');
|
_log.warning('Not authenticated');
|
||||||
|
|
|
@ -86,7 +86,8 @@ class LocalAuthStrategy<User> extends AuthStrategy<User> {
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verificationResult == null) {
|
if (verificationResult == null ||
|
||||||
|
(verificationResult is Map && verificationResult.isEmpty)) {
|
||||||
if (options.failureRedirect != null &&
|
if (options.failureRedirect != null &&
|
||||||
options.failureRedirect!.isNotEmpty) {
|
options.failureRedirect!.isNotEmpty) {
|
||||||
await res.redirect(options.failureRedirect, code: 401);
|
await res.redirect(options.failureRedirect, code: 401);
|
||||||
|
@ -99,7 +100,8 @@ class LocalAuthStrategy<User> extends AuthStrategy<User> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
} else if (verificationResult != false) {
|
} else if (verificationResult != false ||
|
||||||
|
(verificationResult is Map && verificationResult.isNotEmpty)) {
|
||||||
return verificationResult;
|
return verificationResult;
|
||||||
} else {
|
} else {
|
||||||
_log.info('Not authenticated');
|
_log.info('Not authenticated');
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: angel3_auth
|
name: angel3_auth
|
||||||
description: A complete authentication plugin for Angel. Includes support for stateless JWT tokens, Basic Auth, and more.
|
description: A complete authentication plugin for Angel. Includes support for stateless JWT tokens, Basic Auth, and more.
|
||||||
version: 4.0.4
|
version: 4.0.5
|
||||||
homepage: https://angel3-framework.web.app/
|
homepage: https://angel3-framework.web.app/
|
||||||
repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/auth
|
repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/auth
|
||||||
environment:
|
environment:
|
||||||
|
|
|
@ -12,14 +12,16 @@ final AngelAuth<Map<String, String>> auth = AngelAuth<Map<String, String>>(
|
||||||
var headers = <String, String>{'accept': 'application/json'};
|
var headers = <String, String>{'accept': 'application/json'};
|
||||||
var localOpts = AngelAuthOptions<Map<String, String>>(
|
var localOpts = AngelAuthOptions<Map<String, String>>(
|
||||||
failureRedirect: '/failure', successRedirect: '/success');
|
failureRedirect: '/failure', successRedirect: '/success');
|
||||||
|
var localOpts2 =
|
||||||
|
AngelAuthOptions<Map<String, String>>(canRespondWithJson: false);
|
||||||
|
|
||||||
Map<String, String> sampleUser = {'hello': 'world'};
|
Map<String, String> sampleUser = {'hello': 'world'};
|
||||||
|
|
||||||
Future<Map<String, String>?> verifier(
|
Future<Map<String, String>> verifier(String? username, String? password) async {
|
||||||
String? username, String? password) async {
|
|
||||||
if (username == 'username' && password == 'password') {
|
if (username == 'username' && password == 'password') {
|
||||||
return sampleUser;
|
return sampleUser;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +48,7 @@ void main() async {
|
||||||
app.get('/hello', (req, res) {
|
app.get('/hello', (req, res) {
|
||||||
// => 'Woo auth'
|
// => 'Woo auth'
|
||||||
return 'Woo auth';
|
return 'Woo auth';
|
||||||
}, middleware: [auth.authenticate('local')]);
|
}, middleware: [auth.authenticate('local', localOpts2)]);
|
||||||
app.post('/login', (req, res) => 'This should not be shown',
|
app.post('/login', (req, res) => 'This should not be shown',
|
||||||
middleware: [auth.authenticate('local', localOpts)]);
|
middleware: [auth.authenticate('local', localOpts)]);
|
||||||
app.get('/success', (req, res) => 'yep', middleware: [
|
app.get('/success', (req, res) => 'yep', middleware: [
|
||||||
|
|
Loading…
Reference in a new issue