Bump to 2.2.0

This commit is contained in:
Tobe O 2019-05-02 03:28:38 -04:00
parent 2d9630243f
commit e960bdd49f
15 changed files with 135 additions and 131 deletions

View file

@ -1,3 +1,7 @@
# 2.2.0
* Pass `client` to `exchangeAuthorizationCodeForToken`.
* Apply `package:pedantic`.
# 2.1.0
* Updates
* Support `device_code` grants.

View file

@ -39,7 +39,7 @@ but that it can also verify its identity via a `client_secret`.
```dart
class _Server extends AuthorizationServer<PseudoApplication, Map> {
final Uuid _uuid = new Uuid();
final Uuid _uuid = Uuid();
@override
FutureOr<PseudoApplication> findClient(String clientId) {
@ -80,7 +80,7 @@ Future<AuthorizationCodeResponse> exchangeAuthCodeForAccessToken(
String redirectUri,
RequestContext req,
ResponseContext res) async {
return new AuthorizationCodeResponse('foo', refreshToken: 'bar');
return AuthorizationCodeResponse('foo', refreshToken: 'bar');
}
```
@ -137,7 +137,7 @@ Future requestAuthorizationCode(
// At this point, store `pkce.codeChallenge` and `pkce.codeChallengeMethod`,
// so that when it's time to exchange the auth code for a token, we can
// create a new [Pkce] object, and verify the client.
// create a [Pkce] object, and verify the client.
return await getAuthCodeSomehow(client, pkce.codeChallenge, pkce.codeChallengeMethod);
}
@ -159,14 +159,14 @@ Future<AuthorizationTokenResponse> exchangeAuthorizationCodeForToken(
var codeChallenge = await getTheChallenge();
var codeChallengeMethod = await getTheChallengeMethod();
// Make a new [Pkce] object.
var pkce = new Pkce(codeChallengeMethod, codeChallenge);
// Make a [Pkce] object.
var pkce = Pkce(codeChallengeMethod, codeChallenge);
// Call `validate`. If the client is invalid, it throws an OAuth2 exception.
pkce.validate(codeVerifier);
// If we reach here, we know that the `code_verifier` was valid,
// so we can return our authorization token as per usual.
return new AuthorizationTokenResponse('...');
return AuthorizationTokenResponse('...');
}
```

View file

@ -1,3 +1,8 @@
include: package:pedantic/analysis_options.yaml
analyzer:
strong-mode:
implicit-casts: false
linter:
rules:
- unnecessary_const
- unnecessary_new

View file

@ -4,9 +4,9 @@ import 'package:angel_framework/angel_framework.dart';
import 'package:angel_oauth2/angel_oauth2.dart';
main() async {
var app = new Angel();
var oauth2 = new _ExampleAuthorizationServer();
var _rgxBearer = new RegExp(r'^[Bb]earer ([^\n\s]+)$');
var app = Angel();
var oauth2 = _ExampleAuthorizationServer();
var _rgxBearer = RegExp(r'^[Bb]earer ([^\n\s]+)$');
app.group('/auth', (router) {
router
@ -40,13 +40,13 @@ class _ExampleAuthorizationServer
@override
FutureOr<ThirdPartyApp> findClient(String clientId) {
// TODO: Add your code to find the app associated with a client ID.
throw new UnimplementedError();
throw UnimplementedError();
}
@override
FutureOr<bool> verifyClient(ThirdPartyApp client, String clientSecret) {
// TODO: Add your code to verify a client secret, if given one.
throw new UnimplementedError();
throw UnimplementedError();
}
@override
@ -58,17 +58,18 @@ class _ExampleAuthorizationServer
RequestContext req,
ResponseContext res) {
// TODO: In many cases, here you will render a view displaying to the user which scopes are being requested.
throw new UnimplementedError();
throw UnimplementedError();
}
@override
FutureOr<AuthorizationTokenResponse> exchangeAuthorizationCodeForToken(
ThirdPartyApp client,
String authCode,
String redirectUri,
RequestContext req,
ResponseContext res) {
// TODO: Here, you'll convert the auth code into a full-fledged token.
// You might have the auth code stored in a database somewhere.
throw new UnimplementedError();
throw UnimplementedError();
}
}

View file

@ -52,7 +52,7 @@ class ErrorResponse {
/// The authorization request is still pending as the end user hasn't
/// yet completed the user interaction steps (Section 3.3). The
/// client SHOULD repeat the Access Token Request to the token
/// endpoint (a process known as polling). Before each new request
/// endpoint (a process known as polling). Before each request
/// the client MUST wait at least the number of seconds specified by
/// the "interval" parameter of the Device Authorization Response (see
/// Section 3.2), or 5 seconds if none was provided, and respect any
@ -66,7 +66,7 @@ class ErrorResponse {
static const String slowDown = 'slow_down';
/// The "device_code" has expired and the device flow authorization
/// session has concluded. The client MAY commence a new Device
/// session has concluded. The client MAY commence a Device
/// Authorization Request but SHOULD wait for user interaction before
/// restarting to avoid unnecessary polling.
static const String expiredToken = 'expired_token';

View file

@ -23,20 +23,20 @@ class Pkce {
data['code_challenge_method']?.toString() ?? 'plain';
if (codeChallengeMethod != 'plain' && codeChallengeMethod != 's256') {
throw new AuthorizationException(new ErrorResponse(
throw AuthorizationException(ErrorResponse(
ErrorResponse.invalidRequest,
"The `code_challenge_method` parameter must be either 'plain' or 's256'.",
state,
uri: uri));
} else if (codeChallenge?.isNotEmpty != true) {
throw new AuthorizationException(new ErrorResponse(
throw AuthorizationException(ErrorResponse(
ErrorResponse.invalidRequest,
'Missing `code_challenge` parameter.',
state,
uri: uri));
}
return new Pkce(codeChallengeMethod, codeChallenge);
return Pkce(codeChallengeMethod, codeChallenge);
}
/// Returns [true] if the [codeChallengeMethod] is `plain`.
@ -57,8 +57,8 @@ class Pkce {
}
if (foreignChallenge != codeChallenge) {
throw new AuthorizationException(
new ErrorResponse(ErrorResponse.invalidGrant,
throw AuthorizationException(
ErrorResponse(ErrorResponse.invalidGrant,
"The given `code_verifier` parameter is invalid.", state,
uri: uri),
);

View file

@ -11,7 +11,7 @@ typedef FutureOr<AuthorizationTokenResponse> ExtensionGrant(
RequestContext req, ResponseContext res);
Future<String> _getParam(RequestContext req, String name, String state,
{bool body: false, bool throwIfEmpty: true}) async {
{bool body = false, bool throwIfEmpty = true}) async {
Map<String, dynamic> data;
if (body == true) {
@ -23,8 +23,8 @@ Future<String> _getParam(RequestContext req, String name, String state,
var value = data.containsKey(name) ? data[name]?.toString() : null;
if (value?.isNotEmpty != true && throwIfEmpty) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.invalidRequest,
'Missing required parameter "$name".',
state,
@ -37,7 +37,7 @@ Future<String> _getParam(RequestContext req, String name, String state,
}
Future<Iterable<String>> _getScopes(RequestContext req,
{bool body: false}) async {
{bool body = false}) async {
Map<String, dynamic> data;
if (body == true) {
@ -67,23 +67,19 @@ abstract class AuthorizationServer<Client, User> {
/// Retrieves the PKCE `code_verifier` parameter from a [RequestContext], or throws.
Future<String> getPkceCodeVerifier(RequestContext req,
{bool body: true, String state, Uri uri}) async {
{bool body = true, String state, Uri uri}) async {
var data = body
? await req.parseBody().then((_) => req.bodyAsMap)
: req.queryParameters;
var codeVerifier = data['code_verifier'];
if (codeVerifier == null) {
throw new AuthorizationException(new ErrorResponse(
ErrorResponse.invalidRequest,
"Missing `code_verifier` parameter.",
state,
throw AuthorizationException(ErrorResponse(ErrorResponse.invalidRequest,
"Missing `code_verifier` parameter.", state,
uri: uri));
} else if (codeVerifier is! String) {
throw new AuthorizationException(new ErrorResponse(
ErrorResponse.invalidRequest,
"The `code_verifier` parameter must be a string.",
state,
throw AuthorizationException(ErrorResponse(ErrorResponse.invalidRequest,
"The `code_verifier` parameter must be a string.", state,
uri: uri));
} else {
return codeVerifier as String;
@ -100,8 +96,8 @@ abstract class AuthorizationServer<Client, User> {
String state,
RequestContext req,
ResponseContext res) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unsupportedResponseType,
'Authorization code grants are not supported.',
state,
@ -121,8 +117,8 @@ abstract class AuthorizationServer<Client, User> {
String state,
RequestContext req,
ResponseContext res) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unsupportedResponseType,
'Authorization code grants are not supported.',
state,
@ -133,12 +129,13 @@ abstract class AuthorizationServer<Client, User> {
/// Exchanges an authorization code for an authorization token.
FutureOr<AuthorizationTokenResponse> exchangeAuthorizationCodeForToken(
Client client,
String authCode,
String redirectUri,
RequestContext req,
ResponseContext res) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unsupportedResponseType,
'Authorization code grants are not supported.',
req.uri.queryParameters['state'] ?? '',
@ -155,8 +152,8 @@ abstract class AuthorizationServer<Client, User> {
RequestContext req,
ResponseContext res) async {
var body = await req.parseBody().then((_) => req.bodyAsMap);
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unsupportedResponseType,
'Refreshing authorization tokens is not supported.',
body['state']?.toString() ?? '',
@ -174,8 +171,8 @@ abstract class AuthorizationServer<Client, User> {
RequestContext req,
ResponseContext res) async {
var body = await req.parseBody().then((_) => req.bodyAsMap);
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unsupportedResponseType,
'Resource owner password credentials grants are not supported.',
body['state']?.toString() ?? '',
@ -188,8 +185,8 @@ abstract class AuthorizationServer<Client, User> {
FutureOr<AuthorizationTokenResponse> clientCredentialsGrant(
Client client, RequestContext req, ResponseContext res) async {
var body = await req.parseBody().then((_) => req.bodyAsMap);
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unsupportedResponseType,
'Client credentials grants are not supported.',
body['state']?.toString() ?? '',
@ -202,8 +199,8 @@ abstract class AuthorizationServer<Client, User> {
FutureOr<DeviceCodeResponse> requestDeviceCode(Client client,
Iterable<String> scopes, RequestContext req, ResponseContext res) async {
var body = await req.parseBody().then((_) => req.bodyAsMap);
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unsupportedResponseType,
'Device code grants are not supported.',
body['state']?.toString() ?? '',
@ -220,8 +217,8 @@ abstract class AuthorizationServer<Client, User> {
RequestContext req,
ResponseContext res) async {
var body = await req.parseBody().then((_) => req.bodyAsMap);
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unsupportedResponseType,
'Device code grants are not supported.',
body['state']?.toString() ?? '',
@ -241,19 +238,18 @@ abstract class AuthorizationServer<Client, User> {
var responseType = await _getParam(req, 'response_type', state);
req.container.registerLazySingleton<Pkce>((_) {
return new Pkce.fromJson(req.queryParameters, state: state);
return Pkce.fromJson(req.queryParameters, state: state);
});
if (responseType == 'code') {
// Ensure client ID
// TODO: Handle confidential clients
var clientId = await _getParam(req, 'client_id', state);
// Find client
var client = await findClient(clientId);
if (client == null) {
throw new AuthorizationException(new ErrorResponse(
throw AuthorizationException(ErrorResponse(
ErrorResponse.unauthorizedClient,
'Unknown client "$clientId".',
state,
@ -275,7 +271,7 @@ abstract class AuthorizationServer<Client, User> {
var client = await findClient(clientId);
if (client == null) {
throw new AuthorizationException(new ErrorResponse(
throw AuthorizationException(ErrorResponse(
ErrorResponse.unauthorizedClient,
'Unknown client "$clientId".',
state,
@ -307,8 +303,8 @@ abstract class AuthorizationServer<Client, User> {
if (token.scope != null)
queryParameters['scope'] = token.scope.join(' ');
var fragment = queryParameters.keys
.fold<StringBuffer>(new StringBuffer(), (buf, k) {
var fragment =
queryParameters.keys.fold<StringBuffer>(StringBuffer(), (buf, k) {
if (buf.isNotEmpty) buf.write('&');
return buf
..write(
@ -320,8 +316,8 @@ abstract class AuthorizationServer<Client, User> {
res.redirect(target.toString());
return false;
} on FormatException {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.invalidRequest,
'Invalid URI provided as "redirect_uri" parameter',
state,
@ -330,8 +326,8 @@ abstract class AuthorizationServer<Client, User> {
}
}
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.invalidRequest,
'Invalid or no "response_type" parameter provided',
state,
@ -340,8 +336,8 @@ abstract class AuthorizationServer<Client, User> {
} on AngelHttpException {
rethrow;
} catch (e, st) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.serverError,
_internalServerError,
state,
@ -353,8 +349,8 @@ abstract class AuthorizationServer<Client, User> {
}
}
static final RegExp _rgxBasic = new RegExp(r'Basic ([^$]+)');
static final RegExp _rgxBasicAuth = new RegExp(r'([^:]*):([^$]*)');
static final RegExp _rgxBasic = RegExp(r'Basic ([^$]+)');
static final RegExp _rgxBasicAuth = RegExp(r'([^:]*):([^$]*)');
/// A request handler that either exchanges authorization codes for authorization tokens,
/// or refreshes authorization tokens.
@ -369,7 +365,7 @@ abstract class AuthorizationServer<Client, User> {
state = body['state']?.toString() ?? '';
req.container.registerLazySingleton<Pkce>((_) {
return new Pkce.fromJson(req.bodyAsMap, state: state);
return Pkce.fromJson(req.bodyAsMap, state: state);
});
var grantType = await _getParam(req, 'grant_type', state,
@ -383,12 +379,12 @@ abstract class AuthorizationServer<Client, User> {
if (match != null) {
match = _rgxBasicAuth
.firstMatch(new String.fromCharCodes(base64Url.decode(match[1])));
.firstMatch(String.fromCharCodes(base64Url.decode(match[1])));
}
if (match == null) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unauthorizedClient,
'Invalid or no "Authorization" header.',
state,
@ -400,8 +396,8 @@ abstract class AuthorizationServer<Client, User> {
client = await findClient(clientId);
if (client == null) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unauthorizedClient,
'Invalid "client_id" parameter.',
state,
@ -411,8 +407,8 @@ abstract class AuthorizationServer<Client, User> {
}
if (!await verifyClient(client, clientSecret)) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unauthorizedClient,
'Invalid "client_secret" parameter.',
state,
@ -428,7 +424,7 @@ abstract class AuthorizationServer<Client, User> {
var redirectUri =
await _getParam(req, 'redirect_uri', state, body: true);
response = await exchangeAuthorizationCodeForToken(
code, redirectUri, req, res);
client, code, redirectUri, req, res);
} else if (grantType == 'refresh_token') {
var refreshToken =
await _getParam(req, 'refresh_token', state, body: true);
@ -446,7 +442,7 @@ abstract class AuthorizationServer<Client, User> {
if (response.refreshToken != null) {
// Remove refresh token
response = new AuthorizationTokenResponse(
response = AuthorizationTokenResponse(
response.accessToken,
expiresIn: response.expiresIn,
scope: response.scope,
@ -460,8 +456,8 @@ abstract class AuthorizationServer<Client, User> {
client = await findClient(clientId);
if (client == null) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unauthorizedClient,
'Invalid "client_id" parameter.',
state,
@ -479,8 +475,8 @@ abstract class AuthorizationServer<Client, User> {
client = await findClient(clientId);
if (client == null) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.unauthorizedClient,
'Invalid "client_id" parameter.',
state,
@ -499,8 +495,8 @@ abstract class AuthorizationServer<Client, User> {
..addAll(response.toJson());
}
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.invalidRequest,
'Invalid or no "grant_type" parameter provided',
state,
@ -510,8 +506,8 @@ abstract class AuthorizationServer<Client, User> {
} on AngelHttpException {
rethrow;
} catch (e, st) {
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.serverError,
_internalServerError,
state,

View file

@ -2,7 +2,7 @@ name: angel_oauth2
author: Tobe O <thosakwe@gmail.com>
description: A class containing handlers that can be used within Angel to build a spec-compliant OAuth 2.0 server.
homepage: https://github.com/angel-dart/oauth2.git
version: 2.1.0
version: 2.2.0
environment:
sdk: ">=2.0.0-dev <3.0.0"
dependencies:
@ -14,5 +14,6 @@ dev_dependencies:
angel_test: ^2.0.0-alpha
logging:
oauth2: ^1.0.0
pedantic: ^1.0.0
test: ^1.0.0
uuid: ^1.0.0

View file

@ -17,11 +17,11 @@ main() {
TestClient testClient;
setUp(() async {
app = new Angel();
app = Angel();
app.configuration['properties'] = app.configuration;
app.container.registerSingleton(new AuthCodes());
app.container.registerSingleton(AuthCodes());
var server = new _Server();
var server = _Server();
app.group('/oauth2', (router) {
router
@ -29,14 +29,14 @@ main() {
..post('/token', server.tokenEndpoint);
});
app.logger = new Logger('angel')
app.logger = Logger('angel')
..onRecord.listen((rec) {
print(rec);
if (rec.error != null) print(rec.error);
if (rec.stackTrace != null) print(rec.stackTrace);
});
var http = new AngelHttp(app);
var http = AngelHttp(app);
var s = await http.startServer();
var url = 'http://${s.address.address}:${s.port}';
authorizationEndpoint = Uri.parse('$url/oauth2/authorize');
@ -52,7 +52,7 @@ main() {
group('auth code', () {
oauth2.AuthorizationCodeGrant createGrant() =>
new oauth2.AuthorizationCodeGrant(
oauth2.AuthorizationCodeGrant(
pseudoApplication.id,
authorizationEndpoint,
tokenEndpoint,
@ -119,7 +119,7 @@ main() {
}
class _Server extends AuthorizationServer<PseudoApplication, Map> {
final Uuid _uuid = new Uuid();
final Uuid _uuid = Uuid();
@override
FutureOr<PseudoApplication> findClient(String clientId) {
@ -155,6 +155,7 @@ class _Server extends AuthorizationServer<PseudoApplication, Map> {
@override
Future<AuthorizationTokenResponse> exchangeAuthorizationCodeForToken(
PseudoApplication client,
String authCode,
String redirectUri,
RequestContext req,
@ -162,7 +163,7 @@ class _Server extends AuthorizationServer<PseudoApplication, Map> {
var authCodes = req.container.make<AuthCodes>();
var state = authCodes[authCode];
var refreshToken = state == 'can_refresh' ? '${authCode}_refresh' : null;
return new AuthorizationTokenResponse('${authCode}_access',
return AuthorizationTokenResponse('${authCode}_access',
refreshToken: refreshToken);
}
}

View file

@ -11,8 +11,8 @@ main() {
TestClient client;
setUp(() async {
var app = new Angel();
var oauth2 = new _AuthorizationServer();
var app = Angel();
var oauth2 = _AuthorizationServer();
app.group('/oauth2', (router) {
router
@ -47,7 +47,7 @@ main() {
allOf(
hasStatus(200),
hasContentType('application/json'),
hasValidBody(new Validator({
hasValidBody(Validator({
'token_type': equals('bearer'),
'access_token': equals('foo'),
})),
@ -101,6 +101,6 @@ class _AuthorizationServer
@override
Future<AuthorizationTokenResponse> clientCredentialsGrant(
PseudoApplication client, RequestContext req, ResponseContext res) async {
return new AuthorizationTokenResponse('foo');
return AuthorizationTokenResponse('foo');
}
}

View file

@ -1,5 +1,5 @@
const PseudoApplication pseudoApplication =
const PseudoApplication('foo', 'bar', 'http://foo.bar/baz');
PseudoApplication('foo', 'bar', 'http://foo.bar/baz');
class PseudoApplication {
final String id, secret, redirectUri;
@ -7,10 +7,10 @@ class PseudoApplication {
const PseudoApplication(this.id, this.secret, this.redirectUri);
}
const List<PseudoUser> pseudoUsers = const [
const PseudoUser(username: 'foo', password: 'bar'),
const PseudoUser(username: 'michael', password: 'jackson'),
const PseudoUser(username: 'jon', password: 'skeet'),
const List<PseudoUser> pseudoUsers = [
PseudoUser(username: 'foo', password: 'bar'),
PseudoUser(username: 'michael', password: 'jackson'),
PseudoUser(username: 'jon', password: 'skeet'),
];
class PseudoUser {

View file

@ -11,8 +11,8 @@ main() {
TestClient client;
setUp(() async {
var app = new Angel();
var oauth2 = new _AuthorizationServer();
var app = Angel();
var oauth2 = _AuthorizationServer();
app.group('/oauth2', (router) {
router
@ -20,7 +20,7 @@ main() {
..post('/token', oauth2.tokenEndpoint);
});
app.logger = new Logger('angel_oauth2')
app.logger = Logger('angel_oauth2')
..onRecord.listen((rec) {
print(rec);
if (rec.error != null) print(rec.error);
@ -145,7 +145,7 @@ class _AuthorizationServer
@override
FutureOr<DeviceCodeResponse> requestDeviceCode(PseudoApplication client,
Iterable<String> scopes, RequestContext req, ResponseContext res) {
return new DeviceCodeResponse(
return DeviceCodeResponse(
'foo',
'bar',
Uri.parse('https://regiostech.com')
@ -161,12 +161,12 @@ class _AuthorizationServer
RequestContext req,
ResponseContext res) {
if (deviceCode == 'brute') {
throw new AuthorizationException(new ErrorResponse(
throw AuthorizationException(ErrorResponse(
ErrorResponse.slowDown,
"Ho, brother! Ho, whoa, whoa, whoa now! You got too much dip on your chip!",
state));
}
return new AuthorizationTokenResponse('foo');
return AuthorizationTokenResponse('foo');
}
}

View file

@ -10,8 +10,8 @@ main() {
TestClient client;
setUp(() async {
var app = new Angel();
var oauth2 = new _AuthorizationServer();
var app = Angel();
var oauth2 = _AuthorizationServer();
app.group('/oauth2', (router) {
router
@ -65,6 +65,6 @@ class _AuthorizationServer
String state,
RequestContext req,
ResponseContext res) async {
return new AuthorizationTokenResponse('foo');
return AuthorizationTokenResponse('foo');
}
}

View file

@ -12,8 +12,8 @@ main() {
Uri tokenEndpoint;
setUp(() async {
app = new Angel();
var auth = new _AuthorizationServer();
app = Angel();
var auth = _AuthorizationServer();
app.group('/oauth2', (router) {
router
@ -25,9 +25,9 @@ main() {
res.json(e.toJson());
};
app.logger = new Logger('password_test')..onRecord.listen(print);
app.logger = Logger('password_test')..onRecord.listen(print);
var http = new AngelHttp(app);
var http = AngelHttp(app);
var server = await http.startServer();
var url = 'http://${server.address.address}:${server.port}';
tokenEndpoint = Uri.parse('$url/oauth2/token');
@ -61,7 +61,7 @@ main() {
secret: 'bar',
);
throw new StateError('should fail');
throw StateError('should fail');
} on oauth2.AuthorizationException catch (e) {
expect(e.error, ErrorResponse.accessDenied);
} finally {
@ -105,7 +105,7 @@ class _AuthorizationServer
Iterable<String> scopes,
RequestContext req,
ResponseContext res) async {
return new AuthorizationTokenResponse('baz', refreshToken: 'bar');
return AuthorizationTokenResponse('baz', refreshToken: 'bar');
}
@override
@ -122,8 +122,8 @@ class _AuthorizationServer
if (user == null) {
var body = await req.parseBody().then((_) => req.bodyAsMap);
throw new AuthorizationException(
new ErrorResponse(
throw AuthorizationException(
ErrorResponse(
ErrorResponse.accessDenied,
'Invalid username or password.',
body['state']?.toString() ?? '',
@ -132,6 +132,6 @@ class _AuthorizationServer
);
}
return new AuthorizationTokenResponse('foo', refreshToken: 'bar');
return AuthorizationTokenResponse('foo', refreshToken: 'bar');
}
}

View file

@ -6,21 +6,19 @@ import 'package:angel_framework/http.dart';
import 'package:angel_oauth2/angel_oauth2.dart';
import 'package:angel_test/angel_test.dart';
import 'package:logging/logging.dart';
import 'package:oauth2/oauth2.dart' as oauth2;
import 'package:test/test.dart';
import 'package:uuid/uuid.dart';
import 'common.dart';
main() {
Angel app;
Uri authorizationEndpoint, tokenEndpoint, redirectUri;
Uri authorizationEndpoint, tokenEndpoint;
TestClient testClient;
setUp(() async {
app = new Angel();
app.container.registerSingleton(new AuthCodes());
app = Angel();
app.container.registerSingleton(AuthCodes());
var server = new _Server();
var server = _Server();
app.group('/oauth2', (router) {
router
@ -28,19 +26,18 @@ main() {
..post('/token', server.tokenEndpoint);
});
app.logger = new Logger('angel')
app.logger = Logger('angel')
..onRecord.listen((rec) {
print(rec);
if (rec.error != null) print(rec.error);
if (rec.stackTrace != null) print(rec.stackTrace);
});
var http = new AngelHttp(app);
var http = AngelHttp(app);
var s = await http.startServer();
var url = 'http://${s.address.address}:${s.port}';
authorizationEndpoint = Uri.parse('$url/oauth2/authorize');
tokenEndpoint = Uri.parse('$url/oauth2/token');
redirectUri = Uri.parse('http://foo.bar/baz');
testClient = await connectTo(app);
});
@ -228,8 +225,6 @@ main() {
}
class _Server extends AuthorizationServer<PseudoApplication, Map> {
final Uuid _uuid = new Uuid();
@override
FutureOr<PseudoApplication> findClient(String clientId) {
return pseudoApplication;
@ -255,14 +250,15 @@ class _Server extends AuthorizationServer<PseudoApplication, Map> {
@override
Future<AuthorizationTokenResponse> exchangeAuthorizationCodeForToken(
PseudoApplication client,
String authCode,
String redirectUri,
RequestContext req,
ResponseContext res) async {
var codeVerifier = await getPkceCodeVerifier(req);
var pkce = new Pkce('plain', 'hello');
var pkce = Pkce('plain', 'hello');
pkce.validate(codeVerifier);
return new AuthorizationTokenResponse('yes');
return AuthorizationTokenResponse('yes');
}
}