Skip to content

Commit 9569b2a

Browse files
committed
Merge branch 'main' of github.com:DutchCodingCompany/oauth_chopper into feature/add_custom_client
# Conflicts: # lib/src/oauth_chopper.dart # lib/src/oauth_grant.dart # pubspec.yaml
2 parents d4c8825 + 4162fe5 commit 9569b2a

16 files changed

+251
-141
lines changed

analysis_options.yaml

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,14 @@
1-
# This file configures the static analysis results for your project (errors,
2-
# warnings, and lints).
3-
#
4-
# This enables the 'recommended' set of lints from `package:lints`.
5-
# This set helps identify many issues that may lead to problems when running
6-
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
7-
# style and format.
8-
#
9-
# If you want a smaller set of lints you can change this to specify
10-
# 'package:lints/core.yaml'. These are just the most critical lints
11-
# (the recommended set includes the core lints).
12-
# The core lints are also what is used by pub.dev for scoring packages.
13-
14-
include: package:lints/recommended.yaml
15-
16-
# Uncomment the following section to specify additional rules.
17-
18-
# linter:
19-
# rules:
20-
# - camel_case_types
21-
22-
# analyzer:
23-
# exclude:
24-
# - path/to/excluded/files/**
25-
26-
# For more information about the core and recommended set of lints, see
27-
# https://dart.dev/go/core-lints
28-
29-
# For additional information about configuring this file, see
30-
# https://dart.dev/guides/language/analysis-options
1+
include: package:very_good_analysis/analysis_options.yaml
2+
3+
analyzer:
4+
errors:
5+
unawaited_futures: warning
6+
avoid_void_async: warning
7+
missing_return: error
8+
missing_required_param: error
9+
invalid_annotation_target: info
10+
11+
language:
12+
strict-casts: true
13+
strict-inference: true
14+
strict-raw-types: true

example/oauth_chopper_example.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// ignore_for_file: unused_local_variable
1+
// ignore because its a example.
2+
// ignore_for_file: unused_local_variable, prefer_const_declarations,
3+
// ignore_for_file: prefer_const_constructors
24

35
import 'package:chopper/chopper.dart';
46
import 'package:oauth_chopper/oauth_chopper.dart';

lib/oauth_chopper.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// OAuthChopper for configuring OAuth authentication with [Chopper].
1+
/// OAuthChopper for configuring OAuth authentication with Chopper.
22
///
33
/// More dartdocs go here.
44
library oauth_chopper;

lib/src/extensions/request.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import 'package:chopper/chopper.dart';
22

3+
/// Helper extension to easily apply a authorization header to a request.
34
extension ChopperRequest on Request {
4-
Request addAuthorizationHeader(String token) {
5-
final newHeaders = Map<String, String>.from(headers);
6-
newHeaders['Authorization'] = 'Bearer $token';
7-
return copyWith(headers: newHeaders);
8-
}
5+
/// Adds a authorization header with a bearer [token] to the request.
6+
Request addAuthorizationHeader(String token) => applyHeader(
7+
this,
8+
'Authorization',
9+
'Bearer $token',
10+
);
911
}

lib/src/oauth_authenticator.dart

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,33 @@ import 'package:chopper/chopper.dart';
44
import 'package:oauth_chopper/oauth_chopper.dart';
55
import 'package:oauth_chopper/src/extensions/request.dart';
66

7+
/// Callback for error handling.
78
typedef OnErrorCallback = void Function(Object, StackTrace);
89

9-
/// OAuthAuthenticator provides a authenticator that handles OAuth authorizations.
10+
/// {@template authenticator}
11+
/// OAuthAuthenticator provides a authenticator that handles
12+
/// OAuth authorizations.
1013
/// When the provided credentials are invalid it tries to refresh them.
11-
/// Can throw a exceptions if no [onError] is passed. When [onError] is passed exception will be passed to [onError]
14+
/// Can throw a exceptions if no [onError] is passed. When [onError] is passed
15+
/// exception will be passed to [onError]
16+
/// {@endtemplate}
1217
class OAuthAuthenticator extends Authenticator {
18+
/// {@macro authenticator}
1319
OAuthAuthenticator(this.oauthChopper, this.onError);
1420

21+
/// Callback for error handling.
1522
final OnErrorCallback? onError;
23+
24+
/// The [OAuthChopper] instance to get the token from and
25+
/// to refresh the token.
1626
final OAuthChopper oauthChopper;
1727

1828
@override
19-
FutureOr<Request?> authenticate(Request request, Response<dynamic> response,
20-
[Request? originalRequest]) async {
29+
FutureOr<Request?> authenticate(
30+
Request request,
31+
Response<dynamic> response, [
32+
Request? originalRequest,
33+
]) async {
2134
final token = await oauthChopper.token;
2235
if (response.statusCode == 401 && token != null) {
2336
try {

lib/src/oauth_chopper.dart

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import 'package:oauth_chopper/src/oauth_token.dart';
99
import 'package:oauth_chopper/src/storage/memory_storage.dart';
1010
import 'package:oauth_chopper/src/storage/oauth_storage.dart';
1111

12-
/// OAuthChopper client for configuring OAuth authentication with [Chopper].
12+
/// {@template oauth_chopper}
13+
/// OAuthChopper client for configuring OAuth authentication with Chopper.
1314
///
1415
/// For example:
1516
/// ```dart
@@ -19,7 +20,23 @@ import 'package:oauth_chopper/src/storage/oauth_storage.dart';
1920
/// secret: secret,
2021
/// );
2122
/// ```
23+
/// {@endtemplate}
2224
class OAuthChopper {
25+
/// {@macro oauth_chopper}
26+
OAuthChopper({
27+
required this.authorizationEndpoint,
28+
required this.identifier,
29+
required this.secret,
30+
this.endSessionEndpoint,
31+
this.httpClient,
32+
33+
/// OAuth storage for storing credentials.
34+
/// By default it will use a in memory storage [MemoryStorage].
35+
/// For persisting the credentials implement a custom [OAuthStorage].
36+
/// See [OAuthStorage] for more information.
37+
OAuthStorage? storage,
38+
}) : _storage = storage ?? MemoryStorage();
39+
2340
/// OAuth authorization endpoint.
2441
final Uri authorizationEndpoint;
2542

@@ -33,36 +50,24 @@ class OAuthChopper {
3350
final String secret;
3451

3552
/// OAuth storage for storing credentials.
36-
/// By default it will use a in memory storage. For persisting the credentials implement a custom [OAuthStorage].
53+
/// By default it will use a in memory storage. For persisting the credentials
54+
/// implement a custom [OAuthStorage].
3755
/// See [OAuthStorage] for more information.
3856
final OAuthStorage _storage;
3957

4058
/// Provide a custom [http.Client] which will be passed to [oauth2] and used for making new requests.
4159
final http.Client? httpClient;
4260

43-
OAuthChopper({
44-
required this.authorizationEndpoint,
45-
required this.identifier,
46-
required this.secret,
47-
this.endSessionEndpoint,
48-
this.httpClient,
49-
50-
/// OAuth storage for storing credentials.
51-
/// By default it will use a in memory storage [MemoryStorage]. For persisting the credentials implement a custom [OAuthStorage].
52-
/// See [OAuthStorage] for more information.
53-
OAuthStorage? storage,
54-
}) : _storage = storage ?? MemoryStorage();
55-
5661
/// Get stored [OAuthToken].
5762
Future<OAuthToken?> get token async {
5863
final credentialsJson = await _storage.fetchCredentials();
59-
return credentialsJson != null
60-
? OAuthToken.fromJson(credentialsJson)
61-
: null;
64+
return credentialsJson != null ? OAuthToken.fromJson(credentialsJson) : null;
6265
}
6366

6467
/// Provides an [OAuthAuthenticator] instance.
65-
/// The authenticator can throw exceptions when OAuth authentication fails. If [onError] is provided exceptions will be passed to [onError] and not be thrown.
68+
/// The authenticator can throw exceptions when OAuth authentication fails.
69+
/// If [onError] is provided exceptions will be passed to [onError] and not be
70+
/// thrown.
6671
OAuthAuthenticator authenticator({
6772
/// When provided [onError] handles exceptions if thrown.
6873
OnErrorCallback? onError,
@@ -72,10 +77,12 @@ class OAuthChopper {
7277
/// Provides an [OAuthInterceptor] instance.
7378
OAuthInterceptor get interceptor => OAuthInterceptor(this);
7479

75-
/// Tries to refresh the available credentials and returns a new [OAuthToken] instance.
76-
/// Throws an exception when refreshing fails. If the exception is a [AuthorizationException] it clears the storage.
80+
/// Tries to refresh the available credentials and returns a new [OAuthToken]
81+
/// instance.
82+
/// Throws an exception when refreshing fails. If the exception is a
83+
/// [AuthorizationException] it clears the storage.
7784
/// See [Credentials.refresh]
78-
Future<OAuthToken?> refresh() async {
85+
Future<OAuthToken?> refresh() async {
7986
final credentialsJson = await _storage.fetchCredentials();
8087
if (credentialsJson == null) return null;
8188
final credentials = oauth2.Credentials.fromJson(credentialsJson);
@@ -93,15 +100,17 @@ class OAuthChopper {
93100
}
94101
}
95102

96-
/// Request an [OAuthGrant] and stores the credentials in the [storage].
103+
/// Request an [OAuthGrant] and stores the credentials in the
104+
/// [_storage].
105+
///
97106
/// Currently supported grants:
98107
/// - [ResourceOwnerPasswordGrant]
99108
/// - [ClientCredentialsGrant]
100109
/// - [AuthorizationCodeGrant]
101110
/// Throws an exception if the grant fails.
102111
Future<OAuthToken> requestGrant(OAuthGrant grant) async {
103112
final credentials = await grant.handle(
104-
authorizationEndpoint, identifier, secret, httpClient);
113+
authorizationEndpoint, identifier, secret, httpClient,);
105114

106115
await _storage.saveCredentials(credentials);
107116

lib/src/oauth_grant.dart

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import 'package:http/http.dart' as http;
22
import 'package:oauth2/oauth2.dart' as oauth;
33

4-
abstract class OAuthGrant {
4+
/// {@template oauth_grant}
5+
/// Interface for a OAuth grant.
6+
/// Grants are used to obtain credentials from an authorization server.
7+
/// {@endtemplate}
8+
abstract interface class OAuthGrant {
9+
/// {@macro oauth_grant}
510
const OAuthGrant();
611

12+
/// Obtains credentials from an authorization server.
713
Future<String> handle(
814
Uri authorizationEndpoint,
915
String identifier,
@@ -12,13 +18,24 @@ abstract class OAuthGrant {
1218
);
1319
}
1420

21+
/// {@template resource_owner_password_grant}
1522
/// Obtains credentials using a [resource owner password grant](https://tools.ietf.org/html/rfc6749#section-1.3.3).
16-
class ResourceOwnerPasswordGrant extends OAuthGrant {
23+
///
24+
/// This grant uses the resource owner's [username] and [password] to obtain
25+
/// credentials.
26+
/// {@endtemplate}
27+
class ResourceOwnerPasswordGrant implements OAuthGrant {
28+
/// {@macro resource_owner_password_grant}
29+
const ResourceOwnerPasswordGrant({
30+
required this.username,
31+
required this.password,
32+
});
33+
34+
/// Username used for obtaining credentials.
1735
final String username;
18-
final String password;
1936

20-
const ResourceOwnerPasswordGrant(
21-
{required this.username, required this.password});
37+
/// Password used for obtaining credentials.
38+
final String password;
2239

2340
@override
2441
Future<String> handle(
@@ -39,8 +56,11 @@ class ResourceOwnerPasswordGrant extends OAuthGrant {
3956
}
4057
}
4158

59+
/// {@template client_credentials_grant}
4260
/// Obtains credentials using a [client credentials grant](https://tools.ietf.org/html/rfc6749#section-1.3.4).
43-
class ClientCredentialsGrant extends OAuthGrant {
61+
/// {@endtemplate}
62+
class ClientCredentialsGrant implements OAuthGrant {
63+
/// {@macro client_credentials_grant}
4464
const ClientCredentialsGrant();
4565

4666
@override
@@ -60,8 +80,11 @@ class ClientCredentialsGrant extends OAuthGrant {
6080
}
6181
}
6282

83+
/// {@template authorization_code_grant}
6384
/// Obtains credentials using a [authorization code grant](https://tools.ietf.org/html/rfc6749#section-1.3.1).
64-
class AuthorizationCodeGrant extends OAuthGrant {
85+
/// {@endtemplate}
86+
class AuthorizationCodeGrant implements OAuthGrant {
87+
/// {@macro authorization_code_grant}
6588
const AuthorizationCodeGrant({
6689
required this.tokenEndpoint,
6790
required this.scopes,
@@ -70,10 +93,25 @@ class AuthorizationCodeGrant extends OAuthGrant {
7093
required this.listen,
7194
});
7295

96+
/// A URL provided by the authorization server that this library uses to
97+
/// obtain long-lasting credentials.
98+
///
99+
/// This will usually be listed in the authorization server's OAuth2 API
100+
/// documentation.
73101
final Uri tokenEndpoint;
102+
103+
/// The redirect URL where the resource owner will redirect to.
74104
final Uri redirectUrl;
105+
106+
/// The specific permissions being requested from the authorization server may
107+
/// be specified via [scopes].
75108
final List<String> scopes;
109+
110+
/// Callback used for redirect the authorizationUrl given by the authorization
111+
/// server.
76112
final Future<void> Function(Uri authorizationUri) redirect;
113+
114+
/// Callback used for listening for the redirectUrl.
77115
final Future<Uri> Function(Uri redirectUri) listen;
78116

79117
@override
@@ -89,12 +127,18 @@ class AuthorizationCodeGrant extends OAuthGrant {
89127
tokenEndpoint,
90128
httpClient: httpClient,
91129
);
92-
var authorizationUrl =
93-
grant.getAuthorizationUrl(redirectUrl, scopes: scopes);
130+
131+
final authorizationUrl = grant.getAuthorizationUrl(
132+
redirectUrl,
133+
scopes: scopes,
134+
);
135+
94136
await redirect(authorizationUrl);
95-
var responseUrl = await listen(redirectUrl);
96-
oauth.Client client =
97-
await grant.handleAuthorizationResponse(responseUrl.queryParameters);
137+
final responseUrl = await listen(redirectUrl);
138+
139+
final client = await grant.handleAuthorizationResponse(
140+
responseUrl.queryParameters,
141+
);
98142

99143
return client.credentials.toJson();
100144
}

lib/src/oauth_interceptor.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@ import 'package:chopper/chopper.dart';
44
import 'package:oauth_chopper/oauth_chopper.dart';
55
import 'package:oauth_chopper/src/extensions/request.dart';
66

7-
/// OAuthInterceptor is responsible for adding 'Authorization' header to requests.
8-
/// The header is only added if there is a token available. When no token is available no header is added.
7+
/// {@template oauth_interceptor}
8+
/// OAuthInterceptor is responsible for adding 'Authorization' header to
9+
/// requests.
10+
/// The header is only added if there is a token available. When no token is
11+
/// available no header is added.
912
/// Its added as a Bearer token.
13+
/// {@endtemplate}
1014
class OAuthInterceptor implements RequestInterceptor {
15+
/// {@macro oauth_interceptor}
1116
OAuthInterceptor(this.oauthChopper);
1217

18+
/// The [OAuthChopper] instance to get the token from.
1319
final OAuthChopper oauthChopper;
1420

1521
@override

0 commit comments

Comments
 (0)