2.0.0
This commit is contained in:
parent
5056738ef4
commit
3a5a31c5de
6 changed files with 58 additions and 54 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -71,3 +71,5 @@ com_crashlytics_export_strings.xml
|
|||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
.dart_tool
|
|
@ -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'));
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
analyzer:
|
||||
strong-mode: true
|
||||
strong-mode:
|
||||
implicit-casts: false
|
|
@ -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<String, String>();
|
||||
}
|
||||
|
||||
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<User>(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<Map> matchingUsers = await app.service('users').index({
|
||||
'query': {'githubId': id}
|
||||
});
|
||||
Iterable<Map> 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<String, dynamic> toJson() => {'id': id, 'github_id': githubId};
|
||||
}
|
||||
|
|
|
@ -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<Uri>()),
|
||||
'tokenEndpoint*': anyOf(isString, const isInstanceOf<Uri>()),
|
||||
'authorizationEndpoint*': anyOf(isString, const TypeMatcher<Uri>()),
|
||||
'tokenEndpoint*': anyOf(isString, const TypeMatcher<Uri>()),
|
||||
'callback*': isString,
|
||||
'scopes': const isInstanceOf<Iterable<String>>()
|
||||
'scopes': const TypeMatcher<Iterable<String>>()
|
||||
}, defaultValues: {
|
||||
'scopes': <String>[]
|
||||
}, 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'] ?? <String>[]);
|
||||
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<String>()?.toList() ??
|
||||
<String>[]);
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
|
@ -74,14 +75,13 @@ class AngelAuthOAuth2Options {
|
|||
}
|
||||
}
|
||||
|
||||
class OAuth2Strategy<T> implements AuthStrategy {
|
||||
final FutureOr<T> Function(oauth2.Client) verifier;
|
||||
String name;
|
||||
class OAuth2Strategy<User> implements AuthStrategy<User> {
|
||||
final FutureOr<User> 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<T> implements AuthStrategy {
|
|||
getParameters: _options.getParameters);
|
||||
|
||||
@override
|
||||
Future authenticate(RequestContext req, ResponseContext res,
|
||||
[AngelAuthOptions options]) async {
|
||||
FutureOr<User> authenticate(RequestContext req, ResponseContext res,
|
||||
[AngelAuthOptions<User> options]) async {
|
||||
if (options != null) return authenticateCallback(req, res, options);
|
||||
|
||||
var grant = createGrant();
|
||||
|
@ -110,18 +110,16 @@ class OAuth2Strategy<T> implements AuthStrategy {
|
|||
.getAuthorizationUrl(Uri.parse(_options.callback),
|
||||
scopes: _options.scopes)
|
||||
.toString());
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
Future authenticateCallback(RequestContext req, ResponseContext res,
|
||||
Future<User> 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<bool> canLogout(RequestContext req, ResponseContext res) async => true;
|
||||
}
|
||||
|
|
|
@ -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 <thosakwe@gmail.com>
|
||||
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
|
Loading…
Reference in a new issue