Done?
This commit is contained in:
parent
0de70bfc72
commit
feaab715da
18 changed files with 92 additions and 521 deletions
6
.idea/runConfigurations/Callback_Tests.xml
Normal file
6
.idea/runConfigurations/Callback_Tests.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Callback Tests" type="DartTestRunConfigurationType" factoryName="Dart Test" singleton="true">
|
||||
<option name="filePath" value="$PROJECT_DIR$/test/callback_test.dart" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
|
@ -1,6 +1,6 @@
|
|||
# angel_auth
|
||||
|
||||
![version 1.1.0-dev+12](https://img.shields.io/badge/version-1.1.0--dev+12-red.svg)
|
||||
![version 1.1.0-dev+13](https://img.shields.io/badge/version-1.1.0--dev+13-red.svg)
|
||||
![build status](https://travis-ci.org/angel-dart/auth.svg?branch=master)
|
||||
|
||||
A complete authentication plugin for Angel. Inspired by Passport.
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'auth_token.dart';
|
||||
|
||||
typedef AngelAuthCallback(
|
||||
RequestContext req, ResponseContext res, AuthToken token);
|
||||
|
||||
class AngelAuthOptions {
|
||||
AngelAuthCallback callback;
|
||||
bool canRespondWithJson;
|
||||
String successRedirect;
|
||||
String failureRedirect;
|
||||
|
||||
AngelAuthOptions(
|
||||
{this.canRespondWithJson: true,
|
||||
{this.callback,
|
||||
this.canRespondWithJson: true,
|
||||
this.successRedirect,
|
||||
String this.failureRedirect});
|
||||
}
|
||||
|
|
|
@ -237,6 +237,10 @@ class AngelAuth extends AngelPlugin {
|
|||
|
||||
if (allowCookie) req.cookies.add(new Cookie("token", jwt));
|
||||
|
||||
if (options?.callback != null) {
|
||||
return await options.callback(req, res, jwt);
|
||||
}
|
||||
|
||||
if (options?.canRespondWithJson != false &&
|
||||
req.headers.value("accept") != null &&
|
||||
(req.headers.value("accept").contains("application/json") ||
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
import 'dart:async';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:oauth2/oauth2.dart' as Oauth2;
|
||||
import '../options.dart';
|
||||
import '../strategy.dart';
|
||||
/// Logs a user in based on an incoming OAuth access and refresh token.
|
||||
typedef Future OAuth2AuthVerifier(String accessToken, String refreshToken,
|
||||
Map profile);
|
||||
|
||||
class OAuth2AuthStrategy extends AuthStrategy {
|
||||
@override
|
||||
String name = "oauth2";
|
||||
OAuth2AuthVerifier verifier;
|
||||
|
||||
Uri authEndPoint;
|
||||
Uri tokenEndPoint;
|
||||
String clientId;
|
||||
String clientSecret;
|
||||
Uri callbackUri;
|
||||
List<String> scopes;
|
||||
|
||||
@override
|
||||
Future authenticate(RequestContext req, ResponseContext res,
|
||||
[AngelAuthOptions options_]) async {
|
||||
Oauth2.Client client = await makeGrant().handleAuthorizationResponse(req.query);
|
||||
// Remember: Do stuff
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> canLogout(RequestContext req, ResponseContext res) async {
|
||||
return true;
|
||||
}
|
||||
|
||||
OAuth2AuthStrategy(String this.name, OAuth2AuthVerifier this.verifier,
|
||||
{Uri this.authEndPoint,
|
||||
Uri this.tokenEndPoint,
|
||||
String this.clientId,
|
||||
String this.clientSecret,
|
||||
Uri this.callbackUri,
|
||||
List<String> this.scopes: const[]}) {
|
||||
if (this.authEndPoint == null)
|
||||
throw new ArgumentError.notNull('authEndPoint');
|
||||
if (this.tokenEndPoint == null)
|
||||
throw new ArgumentError.notNull('tokenEndPoint');
|
||||
if (this.clientId == null || this.clientId.isEmpty)
|
||||
throw new ArgumentError.notNull('clientId');
|
||||
}
|
||||
|
||||
call(RequestContext req, ResponseContext res) async {
|
||||
var grant = makeGrant();
|
||||
|
||||
Uri to = grant.getAuthorizationUrl(callbackUri, scopes: scopes);
|
||||
return res.redirect(to.path);
|
||||
}
|
||||
|
||||
Oauth2.AuthorizationCodeGrant makeGrant() {
|
||||
return new Oauth2.AuthorizationCodeGrant(
|
||||
clientId, authEndPoint, tokenEndPoint, secret: clientSecret);
|
||||
}
|
||||
}
|
||||
|
||||
class OAuth2AuthorizationError extends AngelHttpException {
|
||||
OAuth2AuthorizationError({String message: "OAuth2 Authorization Error",
|
||||
List<String> errors: const []})
|
||||
: super.NotAuthenticated(message: message) {
|
||||
this.errors = errors;
|
||||
}
|
||||
}
|
|
@ -1,3 +1 @@
|
|||
export 'local.dart';
|
||||
export 'oauth2.dart';
|
||||
export 'token.dart';
|
||||
export 'local.dart';
|
|
@ -1,16 +0,0 @@
|
|||
import 'dart:async';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import '../options.dart';
|
||||
import '../strategy.dart';
|
||||
|
||||
class JwtAuthStrategy extends AuthStrategy {
|
||||
|
||||
@override
|
||||
Future authenticate(RequestContext req, ResponseContext res,
|
||||
[AngelAuthOptions options]) async {
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> canLogout(RequestContext req, ResponseContext res) async => false;
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
name: angel_auth
|
||||
description: A complete authentication plugin for Angel.
|
||||
version: 1.0.0-dev+12
|
||||
version: 1.0.0-dev+13
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_auth
|
||||
dependencies:
|
||||
angel_framework: ">=1.0.0-dev <2.0.0"
|
||||
crypto: ">=2.0.0 <3.0.0"
|
||||
oauth2: ">= 1.0.2 < 2.0.0"
|
||||
dev_dependencies:
|
||||
http: ">= 0.11.3 < 0.12.0"
|
||||
test: ">= 0.12.13 < 0.13.0"
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
import 'auth_token_test.dart' as authToken;
|
||||
import 'local_test.dart' as local;
|
||||
|
||||
wireAuth(Angel app) async {
|
||||
|
||||
}
|
||||
|
||||
main() async {
|
||||
group('everything', () {
|
||||
Angel app;
|
||||
http.Client client;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
app = new Angel();
|
||||
await app.configure(wireAuth);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
group("JWT (de)serialization", authToken.main);
|
||||
group("local", local.main);
|
||||
|
||||
test('can use login as middleware', () async {
|
||||
|
||||
});
|
||||
|
||||
test('successRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('failureRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('allow everything', () async {
|
||||
|
||||
});
|
||||
|
||||
test('force everything', () async {
|
||||
|
||||
});
|
||||
|
||||
test('logout', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
70
test/callback_test.dart
Normal file
70
test/callback_test.dart
Normal file
|
@ -0,0 +1,70 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
class User extends MemoryModel {
|
||||
String username, password;
|
||||
|
||||
User({this.username, this.password});
|
||||
}
|
||||
|
||||
main() {
|
||||
Angel app;
|
||||
AngelAuth auth;
|
||||
http.Client client;
|
||||
HttpServer server;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
app = new Angel();
|
||||
app.use('/users', new MemoryService<User>());
|
||||
|
||||
await app
|
||||
.service('users')
|
||||
.create({'username': 'jdoe1', 'password': 'password'});
|
||||
|
||||
await app.configure(auth = new AngelAuth());
|
||||
|
||||
auth.serializer = (User user) async => user.id;
|
||||
auth.deserializer = app.service('users').read;
|
||||
|
||||
auth.strategies.add(new LocalAuthStrategy((username, password) async {
|
||||
final List<User> users = await app.service('users').index();
|
||||
final found = users.firstWhere(
|
||||
(user) => user.username == username && user.password == password,
|
||||
orElse: () => null);
|
||||
|
||||
return found != null ? found : false;
|
||||
}));
|
||||
|
||||
app.post(
|
||||
'/login',
|
||||
auth.authenticate('local',
|
||||
new AngelAuthOptions(callback: (req, res, token) {
|
||||
return res
|
||||
..write('Hello!')
|
||||
..end();
|
||||
})));
|
||||
|
||||
client = new http.Client();
|
||||
server = await app.startServer();
|
||||
url = 'http://${server.address.address}:${server.port}';
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
client.close();
|
||||
await server.close(force: true);
|
||||
app = null;
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('login', () async {
|
||||
final response = await client.post('$url/login',
|
||||
body: {'username': 'jdoe1', 'password': 'password'});
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body, equals('Hello!'));
|
||||
});
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
wireAuth(Angel app) async {
|
||||
|
||||
}
|
||||
|
||||
main() async {
|
||||
group('digest', () {
|
||||
Angel app;
|
||||
http.Client client;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
app = new Angel();
|
||||
await app.configure(wireAuth);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('can use login as middleware', () async {
|
||||
|
||||
});
|
||||
|
||||
test('successRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('failureRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('allow digest', () async {
|
||||
|
||||
});
|
||||
|
||||
test('force digest', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
|
@ -3,7 +3,6 @@ import 'dart:io';
|
|||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:merge_map/merge_map.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
final AngelAuth Auth = new AngelAuth();
|
||||
|
@ -43,10 +42,6 @@ main() async {
|
|||
app.get('/success', "yep", middleware: ['auth']);
|
||||
app.get('/failure', "nope");
|
||||
|
||||
app
|
||||
..normalize()
|
||||
..dumpTree();
|
||||
|
||||
HttpServer server =
|
||||
await app.startServer(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
wireAuth(Angel app) async {
|
||||
|
||||
}
|
||||
|
||||
main() async {
|
||||
group('oauth1', () {
|
||||
Angel app;
|
||||
http.Client client;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
app = new Angel();
|
||||
await app.configure(wireAuth);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('can use login as middleware', () async {
|
||||
|
||||
});
|
||||
|
||||
test('successRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('failureRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('allow oauth1', () async {
|
||||
|
||||
});
|
||||
|
||||
test('force oauth1', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
wireAuth(Angel app) async {
|
||||
|
||||
}
|
||||
|
||||
main() async {
|
||||
group('oauth2', () {
|
||||
Angel app;
|
||||
http.Client client;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
app = new Angel();
|
||||
await app.configure(wireAuth);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('can use login as middleware', () async {
|
||||
|
||||
});
|
||||
|
||||
test('successRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('failureRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('allow oauth2', () async {
|
||||
|
||||
});
|
||||
|
||||
test('force oauth2', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
wireAuth(Angel app) async {
|
||||
|
||||
}
|
||||
|
||||
main() async {
|
||||
group('oauth2 in-house', () {
|
||||
Angel app;
|
||||
http.Client client;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
app = new Angel();
|
||||
await app.configure(wireAuth);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('can use login as middleware', () async {
|
||||
|
||||
});
|
||||
|
||||
test('successRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('failureRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('allow oauth2 in-house', () async {
|
||||
|
||||
});
|
||||
|
||||
test('force oauth2 in-house', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
wireAuth(Angel app) async {
|
||||
|
||||
}
|
||||
|
||||
main() async {
|
||||
group('openid', () {
|
||||
Angel app;
|
||||
http.Client client;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
app = new Angel();
|
||||
await app.configure(wireAuth);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('can use login as middleware', () async {
|
||||
|
||||
});
|
||||
|
||||
test('successRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('failureRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('allow openid', () async {
|
||||
|
||||
});
|
||||
|
||||
test('force openid', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
wireAuth(Angel app) async {
|
||||
|
||||
}
|
||||
|
||||
main() async {
|
||||
group('token', () {
|
||||
Angel app;
|
||||
http.Client client;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
app = new Angel();
|
||||
await app.configure(wireAuth);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('can use login as middleware', () async {
|
||||
|
||||
});
|
||||
|
||||
test('successRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('failureRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('allow token', () async {
|
||||
|
||||
});
|
||||
|
||||
test('force token', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:angel_framework/angel_framework.dart';
|
||||
import 'package:angel_auth/angel_auth.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
wireAuth(Angel app) async {
|
||||
|
||||
}
|
||||
|
||||
main() async {
|
||||
group('websocket', () {
|
||||
Angel app;
|
||||
http.Client client;
|
||||
String url;
|
||||
|
||||
setUp(() async {
|
||||
client = new http.Client();
|
||||
app = new Angel();
|
||||
await app.configure(wireAuth);
|
||||
HttpServer server = await app.startServer(
|
||||
InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
url = "http://${server.address.host}:${server.port}";
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await app.httpServer.close(force: true);
|
||||
client = null;
|
||||
url = null;
|
||||
});
|
||||
|
||||
test('can use login as middleware', () async {
|
||||
|
||||
});
|
||||
|
||||
test('successRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('failureRedirect', () async {
|
||||
|
||||
});
|
||||
|
||||
test('allow websocket', () async {
|
||||
|
||||
});
|
||||
|
||||
test('force websocket', () async {
|
||||
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue