From 3a5a31c5de963f213be39dd89582b1387bb60741 Mon Sep 17 00:00:00 2001 From: Tobe O Date: Tue, 11 Sep 2018 23:23:42 -0400 Subject: [PATCH] 2.0.0 --- .gitignore | 2 ++ README.md | 2 +- analysis_options.yaml | 3 ++- example/main.dart | 52 ++++++++++++++++++++------------------ lib/angel_auth_oauth2.dart | 44 +++++++++++++++----------------- pubspec.yaml | 9 ++++--- 6 files changed, 58 insertions(+), 54 deletions(-) diff --git a/.gitignore b/.gitignore index a26910ac..199ba0a0 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,5 @@ com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties + +.dart_tool \ No newline at end of file diff --git a/README.md b/README.md index e7b14ff7..27579958 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ a popup window. In this case, use `confirmPopupAuthentication`, which is bundled configureServer(Angel app) async { // ... var auth = new AngelAuth(); - auth.strategies.add(oauth2Strategy); + auth.strategies['github'] = oauth2Strategy; // Redirect app.get('/auth/github', auth.authenticate('github')); diff --git a/analysis_options.yaml b/analysis_options.yaml index 518eb901..eae1e42a 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,2 +1,3 @@ analyzer: - strong-mode: true \ No newline at end of file + strong-mode: + implicit-casts: false \ No newline at end of file diff --git a/example/main.dart b/example/main.dart index d84141e5..95c98930 100644 --- a/example/main.dart +++ b/example/main.dart @@ -2,7 +2,6 @@ import 'dart:convert'; import 'dart:io'; import 'package:angel_auth/angel_auth.dart'; import 'package:angel_framework/angel_framework.dart'; -import 'package:angel_framework/common.dart'; import 'package:angel_auth_oauth2/angel_auth_oauth2.dart'; import 'package:logging/logging.dart'; import 'package:oauth2/oauth2.dart' as oauth2; @@ -17,45 +16,48 @@ final AngelAuthOAuth2Options oAuth2Config = new AngelAuthOAuth2Options( if (contentType.type == 'application') { if (contentType.subtype == 'x-www-form-urlencoded') return Uri.splitQueryString(body); - else if (contentType.subtype == 'json') return JSON.decode(body); + else if (contentType.subtype == 'json') + return (json.decode(body) as Map).cast(); } - throw new FormatException('Invalid content-type $contentType; expected application/x-www-form-urlencoded or application/json.'); + throw new FormatException( + 'Invalid content-type $contentType; expected application/x-www-form-urlencoded or application/json.'); }); main() async { var app = new Angel(); - app.lazyParseBodies = true; app.use('/users', new MapService()); var auth = new AngelAuth(jwtKey: 'oauth2 example secret', allowCookie: false); auth.deserializer = - (id) => app.service('users').read(id).then((u) => User.parse(u)); + (id) => app.service('users').read(id).then((u) => User.parse(u as Map)); auth.serializer = (User user) async => user.id; - auth.strategies.add( - new OAuth2Strategy('github', oAuth2Config, (oauth2.Client client) async { - var response = await client.get('https://api.github.com/user'); - var ghUser = JSON.decode(response.body); - var id = ghUser['id']; + auth.strategies['github'] = new OAuth2Strategy( + oAuth2Config, + (oauth2.Client client) async { + var response = await client.get('https://api.github.com/user'); + var ghUser = json.decode(response.body); + var id = ghUser['id']; - Iterable matchingUsers = await app.service('users').index({ - 'query': {'githubId': id} - }); + Iterable matchingUsers = await app.service('users').index({ + 'query': {'githubId': id} + }); - if (matchingUsers.isNotEmpty) { - // Return the corresponding user, if it exists - return User.parse(matchingUsers.firstWhere((u) => u['githubId'] == id)); - } else { - // Otherwise,create a user - return await app - .service('users') - .create({'githubId': id}).then((u) => User.parse(u)); - } - })); + if (matchingUsers.isNotEmpty) { + // Return the corresponding user, if it exists + return User.parse(matchingUsers.firstWhere((u) => u['githubId'] == id)); + } else { + // Otherwise,create a user + return await app + .service('users') + .create({'githubId': id}).then((u) => User.parse(u as Map)); + } + }, + ); app.get('/auth/github', auth.authenticate('github')); app.get( @@ -74,7 +76,7 @@ main() async { app.logger = new Logger('angel')..onRecord.listen(print); var http = new AngelHttp(app); - var server = await http.startServer(InternetAddress.LOOPBACK_IP_V4, 3000); + var server = await http.startServer(InternetAddress.loopbackIPv4, 3000); var url = 'http://${server.address.address}:${server.port}'; print('Listening on $url'); print('View user listing: $url/users'); @@ -89,7 +91,7 @@ class User extends Model { User({this.id, this.githubId}); static User parse(Map map) => - new User(id: map['id'], githubId: map['github_id']); + new User(id: map['id'] as String, githubId: map['github_id'] as int); Map toJson() => {'id': id, 'github_id': githubId}; } diff --git a/lib/angel_auth_oauth2.dart b/lib/angel_auth_oauth2.dart index 54d0a824..b24d5895 100644 --- a/lib/angel_auth_oauth2.dart +++ b/lib/angel_auth_oauth2.dart @@ -10,10 +10,10 @@ import 'package:oauth2/oauth2.dart' as oauth2; final Validator OAUTH2_OPTIONS_SCHEMA = new Validator({ 'key*': isString, 'secret*': isString, - 'authorizationEndpoint*': anyOf(isString, const isInstanceOf()), - 'tokenEndpoint*': anyOf(isString, const isInstanceOf()), + 'authorizationEndpoint*': anyOf(isString, const TypeMatcher()), + 'tokenEndpoint*': anyOf(isString, const TypeMatcher()), 'callback*': isString, - 'scopes': const isInstanceOf>() + 'scopes': const TypeMatcher>() }, defaultValues: { 'scopes': [] }, customErrorMessages: { @@ -29,10 +29,10 @@ class AngelAuthOAuth2Options { final String secret; /// The remote endpoint that prompts external users for authentication credentials. - final authorizationEndpoint; + final String authorizationEndpoint; /// The remote endpoint that exchanges auth codes for access tokens. - final tokenEndpoint; + final String tokenEndpoint; /// The callback URL that the OAuth2 server should redirect authenticated users to. final String callback; @@ -55,12 +55,13 @@ class AngelAuthOAuth2Options { factory AngelAuthOAuth2Options.fromJson(Map json) => new AngelAuthOAuth2Options( - key: json['key'], - secret: json['secret'], - authorizationEndpoint: json['authorizationEndpoint'], - tokenEndpoint: json['tokenEndpoint'], - callback: json['callback'], - scopes: json['scopes'] ?? []); + key: json['key'] as String, + secret: json['secret'] as String, + authorizationEndpoint: json['authorizationEndpoint'] as String, + tokenEndpoint: json['tokenEndpoint'] as String, + callback: json['callback'] as String, + scopes: (json['scopes'] as Iterable)?.cast()?.toList() ?? + []); Map toJson() { return { @@ -74,14 +75,13 @@ class AngelAuthOAuth2Options { } } -class OAuth2Strategy implements AuthStrategy { - final FutureOr Function(oauth2.Client) verifier; - String name; +class OAuth2Strategy implements AuthStrategy { + final FutureOr Function(oauth2.Client) verifier; AngelAuthOAuth2Options _options; /// [options] can be either a `Map` or an instance of [AngelAuthOAuth2Options]. - OAuth2Strategy(this.name, options, this.verifier) { + OAuth2Strategy(options, this.verifier) { if (options is AngelAuthOAuth2Options) _options = options; else if (options is Map) @@ -101,8 +101,8 @@ class OAuth2Strategy implements AuthStrategy { getParameters: _options.getParameters); @override - Future authenticate(RequestContext req, ResponseContext res, - [AngelAuthOptions options]) async { + FutureOr authenticate(RequestContext req, ResponseContext res, + [AngelAuthOptions options]) async { if (options != null) return authenticateCallback(req, res, options); var grant = createGrant(); @@ -110,18 +110,16 @@ class OAuth2Strategy implements AuthStrategy { .getAuthorizationUrl(Uri.parse(_options.callback), scopes: _options.scopes) .toString()); - return false; + return null; } - Future authenticateCallback(RequestContext req, ResponseContext res, + Future authenticateCallback(RequestContext req, ResponseContext res, [AngelAuthOptions options]) async { var grant = createGrant(); await grant.getAuthorizationUrl(Uri.parse(_options.callback), scopes: _options.scopes); - var client = await grant.handleAuthorizationResponse(req.query); + var client = + await grant.handleAuthorizationResponse(req.uri.queryParameters); return await verifier(client); } - - @override - Future canLogout(RequestContext req, ResponseContext res) async => true; } diff --git a/pubspec.yaml b/pubspec.yaml index 5cd03915..15782ad5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,11 +1,12 @@ name: angel_auth_oauth2 description: angel_auth strategy for OAuth2 login, i.e. Facebook. -version: 1.0.2 +version: 2.0.0 author: Tobe O environment: - sdk: ">=1.19.0 <3.0.0" + sdk: ">=2.0.0-dev <3.0.0" homepage: https://github.com/angel-dart/auth_oauth2.git dependencies: - angel_auth: ^1.0.0-dev - angel_validate: ^1.0.0-beta + angel_auth: ^2.0.0 + angel_framework: ^2.0.0-alpha + angel_validate: ^2.0.0-alpha oauth2: ^1.0.0 \ No newline at end of file