Skip to content

Commit 3117e90

Browse files
author
Bas de Vaan
authored
Merge pull request #3 from DutchCodingCompany/feature/authorization_code_grant
Feature/authorization code grant
2 parents f4c81f9 + 3825cf3 commit 3117e90

File tree

2 files changed

+54
-10
lines changed

2 files changed

+54
-10
lines changed

lib/src/oauth_grant.dart

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,37 @@ class ClientCredentialsGrant extends OAuthGrant {
4545
}
4646
}
4747

48-
//TODO: Add AuthorizationCodeGrant
48+
/// Obtains credentials using a [authorization code grant](https://tools.ietf.org/html/rfc6749#section-1.3.1).
49+
class AuthorizationCodeGrant extends OAuthGrant {
50+
const AuthorizationCodeGrant({
51+
required this.tokenEndpoint,
52+
required this.scopes,
53+
required this.redirectUrl,
54+
required this.redirect,
55+
required this.listen,
56+
});
57+
58+
final Uri tokenEndpoint;
59+
final Uri redirectUrl;
60+
final List<String> scopes;
61+
final Future<void> Function(Uri authorizationUri) redirect;
62+
final Future<Uri> Function(Uri redirectUri) listen;
63+
64+
@override
65+
Future<String> handle(
66+
Uri authorizationEndpoint, String identifier, String secret) async {
67+
final grant = oauth.AuthorizationCodeGrant(
68+
identifier,
69+
authorizationEndpoint,
70+
tokenEndpoint,
71+
);
72+
var authorizationUrl =
73+
grant.getAuthorizationUrl(redirectUrl, scopes: scopes);
74+
await redirect(authorizationUrl);
75+
var responseUrl = await listen(redirectUrl);
76+
oauth.Client client =
77+
await grant.handleAuthorizationResponse(responseUrl.queryParameters);
78+
79+
return client.credentials.toJson();
80+
}
81+
}

test/oauth_authenticator_test.dart

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ void main() {
2323
),
2424
);
2525
final testRequest = Request('GET', Uri(host: 'test'), Uri(host: 'test'));
26-
final unauthorizedResponse = Response(http.Response('body', HttpStatus.unauthorized), 'body');
27-
final authorizedResponse = Response(http.Response('body', HttpStatus.accepted), 'body');
26+
final unauthorizedResponse =
27+
Response(http.Response('body', HttpStatus.unauthorized), 'body');
28+
final authorizedResponse =
29+
Response(http.Response('body', HttpStatus.accepted), 'body');
2830

2931
test('only refresh on unauthorized and token', () async {
3032
// arrange
@@ -34,7 +36,8 @@ void main() {
3436
final expected = {'Authorization': 'Bearer token'};
3537

3638
// act
37-
final result = await authenticator.authenticate(testRequest, unauthorizedResponse);
39+
final result =
40+
await authenticator.authenticate(testRequest, unauthorizedResponse);
3841

3942
// assert
4043
verify(mockOAuthChopper.refresh()).called(1);
@@ -48,7 +51,8 @@ void main() {
4851
final authenticator = OAuthAuthenticator(mockOAuthChopper, null);
4952

5053
// act
51-
final result = await authenticator.authenticate(testRequest, authorizedResponse);
54+
final result =
55+
await authenticator.authenticate(testRequest, authorizedResponse);
5256

5357
// assert
5458
verifyNever(mockOAuthChopper.refresh());
@@ -62,7 +66,8 @@ void main() {
6266
final authenticator = OAuthAuthenticator(mockOAuthChopper, null);
6367

6468
// act
65-
final result = await authenticator.authenticate(testRequest, unauthorizedResponse);
69+
final result =
70+
await authenticator.authenticate(testRequest, unauthorizedResponse);
6671

6772
// assert
6873
verifyNever(mockOAuthChopper.refresh());
@@ -76,7 +81,8 @@ void main() {
7681
final authenticator = OAuthAuthenticator(mockOAuthChopper, null);
7782

7883
// act
79-
final result = await authenticator.authenticate(testRequest, unauthorizedResponse);
84+
final result =
85+
await authenticator.authenticate(testRequest, unauthorizedResponse);
8086

8187
// assert
8288
verify(mockOAuthChopper.refresh()).called(1);
@@ -91,18 +97,23 @@ void main() {
9197

9298
// act
9399
// assert
94-
expect(() async => await authenticator.authenticate(testRequest, unauthorizedResponse), throwsFormatException);
100+
expect(
101+
() async =>
102+
await authenticator.authenticate(testRequest, unauthorizedResponse),
103+
throwsFormatException);
95104
});
96105

97106
test("Exception not thrown if onError is supplied", () async {
98107
// arrange
99108
FormatException? result;
100109
when(mockOAuthChopper.refresh()).thenThrow(FormatException('failed'));
101110
when(mockOAuthChopper.token).thenAnswer((_) async => testToken);
102-
final authenticator = OAuthAuthenticator(mockOAuthChopper, (e, s) => result = e as FormatException);
111+
final authenticator = OAuthAuthenticator(
112+
mockOAuthChopper, (e, s) => result = e as FormatException);
103113

104114
// act
105-
final responseResult = await authenticator.authenticate(testRequest, unauthorizedResponse);
115+
final responseResult =
116+
await authenticator.authenticate(testRequest, unauthorizedResponse);
106117

107118
// assert
108119
expect(result?.message, 'failed');

0 commit comments

Comments
 (0)