diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e8d333f..a0d84117 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ * Migrated angel_validate to 4.0.0 (7/7 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_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) * Added symbol_table and migrated to 2.0.0 (16/16 tests passed) * Migrated jael to 4.0.0 (20/20 tests passed) diff --git a/packages/auth/CHANGELOG.md b/packages/auth/CHANGELOG.md index 4f5374f9..2ce12295 100644 --- a/packages/auth/CHANGELOG.md +++ b/packages/auth/CHANGELOG.md @@ -1,10 +1,15 @@ # 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 * Changed `serializer` and `deserializer` parameters to be required * Fixed HTTP basic authentication -* Passed all 51 unit tests +* All 31 unit tests passed ## 4.0.3 diff --git a/packages/auth/README.md b/packages/auth/README.md index 00520836..3ffa84a6 100644 --- a/packages/auth/README.md +++ b/packages/auth/README.md @@ -1,6 +1,6 @@ # 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) [![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 -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. +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. ```dart 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`. -`angel3_client` [exposes this as a Stream](https://github.com/dukefirehawk/angel/tree/angel3/packages/client#authentication): +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): ```dart app.authenticateViaPopup('/auth/google').listen((jwt) { diff --git a/packages/auth/lib/src/plugin.dart b/packages/auth/lib/src/plugin.dart index 5fca8b5c..00a73ca5 100644 --- a/packages/auth/lib/src/plugin.dart +++ b/packages/auth/lib/src/plugin.dart @@ -352,9 +352,12 @@ class AngelAuth { /// 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. - RequestHandler authenticate(type, [AngelAuthOptions? options]) { + RequestHandler authenticate(type, [AngelAuthOptions? opt]) { return (RequestContext req, ResponseContext res) async { + var authOption = opt ?? AngelAuthOptions(); + var names = []; + var arr = type is Iterable ? type.map((x) => x.toString()).toList() : [type.toString()]; @@ -386,11 +389,12 @@ class AngelAuth { var hasExisting = reqContainer?.has() ?? false; var result = hasExisting ? reqContainer?.make() - : await strategy.authenticate(req, res, options); + : await strategy.authenticate(req, res, authOption); - if (result != null && result == true) { + if (result == true) { 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); // Create JWT @@ -398,13 +402,13 @@ class AngelAuth { userId: userId, lifeSpan: _jwtLifeSpan, ipAddress: req.ip); var jwt = token.serialize(_hs256); - if (options != null && options.tokenCallback != null) { + if (authOption.tokenCallback != null) { var hasUser = reqContainer?.has() ?? false; if (!hasUser) { reqContainer?.registerSingleton(result); } - var r = await options.tokenCallback!(req, res, token, result); + var r = await authOption.tokenCallback!(req, res, token, result); if (r != null) return r; jwt = token.serialize(_hs256); } @@ -416,24 +420,15 @@ class AngelAuth { } // Options is not null - if (options != null) { - if (options.callback != null) { - return await options.callback!(req, res, jwt); - } + if (authOption.callback != null) { + return await authOption.callback!(req, res, jwt); + } - if (options.successRedirect?.isNotEmpty == true) { - await res.redirect(options.successRedirect); - return false; - } else if (options.canRespondWithJson && - 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')) { + if (authOption.successRedirect?.isNotEmpty == true) { + await res.redirect(authOption.successRedirect); + return false; + } else if (authOption.canRespondWithJson && + req.accepts('application/json')) { var user = hasExisting ? result : await deserializer((await serializer(result)) as Object); @@ -449,8 +444,8 @@ class AngelAuth { res.statusCode == 302 || res.headers.containsKey('location')) { return false; - } else if (options != null && options.failureRedirect != null) { - await res.redirect(options.failureRedirect); + } else if (authOption.failureRedirect != null) { + await res.redirect(authOption.failureRedirect); return false; } else { _log.warning('Not authenticated'); diff --git a/packages/auth/lib/src/strategies/local.dart b/packages/auth/lib/src/strategies/local.dart index 461a3623..1ea91856 100644 --- a/packages/auth/lib/src/strategies/local.dart +++ b/packages/auth/lib/src/strategies/local.dart @@ -86,7 +86,8 @@ class LocalAuthStrategy extends AuthStrategy { //} } - if (verificationResult == null) { + if (verificationResult == null || + (verificationResult is Map && verificationResult.isEmpty)) { if (options.failureRedirect != null && options.failureRedirect!.isNotEmpty) { await res.redirect(options.failureRedirect, code: 401); @@ -99,7 +100,8 @@ class LocalAuthStrategy extends AuthStrategy { } return null; - } else if (verificationResult != false) { + } else if (verificationResult != false || + (verificationResult is Map && verificationResult.isNotEmpty)) { return verificationResult; } else { _log.info('Not authenticated'); diff --git a/packages/auth/pubspec.yaml b/packages/auth/pubspec.yaml index 543614f2..0e92df72 100644 --- a/packages/auth/pubspec.yaml +++ b/packages/auth/pubspec.yaml @@ -1,6 +1,6 @@ name: angel3_auth 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/ repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/auth environment: diff --git a/packages/auth/test/local_test.dart b/packages/auth/test/local_test.dart index 4743f066..3b73b757 100644 --- a/packages/auth/test/local_test.dart +++ b/packages/auth/test/local_test.dart @@ -12,14 +12,16 @@ final AngelAuth> auth = AngelAuth>( var headers = {'accept': 'application/json'}; var localOpts = AngelAuthOptions>( failureRedirect: '/failure', successRedirect: '/success'); +var localOpts2 = + AngelAuthOptions>(canRespondWithJson: false); + Map sampleUser = {'hello': 'world'}; -Future?> verifier( - String? username, String? password) async { +Future> verifier(String? username, String? password) async { if (username == 'username' && password == 'password') { return sampleUser; } else { - return null; + return {}; } } @@ -46,7 +48,7 @@ void main() async { app.get('/hello', (req, res) { // => 'Woo auth' return 'Woo auth'; - }, middleware: [auth.authenticate('local')]); + }, middleware: [auth.authenticate('local', localOpts2)]); app.post('/login', (req, res) => 'This should not be shown', middleware: [auth.authenticate('local', localOpts)]); app.get('/success', (req, res) => 'yep', middleware: [