| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:async'; | |
| import 'package:http/http.dart' as http; | |
| import 'package:http_parser/http_parser.dart'; | |
| import 'client.dart'; | |
| import 'handle_access_token_response.dart'; | |
| import 'utils.dart'; | |
| /// Obtains credentials using a [client credentials grant](https://tools.ietf.org/html/rfc6749#section-1.3.4). | |
| /// | |
| /// This mode of authorization uses the client's [identifier] and [secret] | |
| /// to obtain an authorization token from the authorization server, instead | |
| /// of sending a user through a dedicated flow. | |
| /// | |
| /// The client [identifier] and [secret] are required, and are | |
| /// used to identify and authenticate your specific OAuth2 client. These are | |
| /// usually global to the program using this library. | |
| /// | |
| /// The specific permissions being requested from the authorization server may | |
| /// be specified via [scopes]. The scope strings are specific to the | |
| /// authorization server and may be found in its documentation. Note that you | |
| /// may not be granted access to every scope you request; you may check the | |
| /// [Credentials.scopes] field of [Client.credentials] to see which scopes you | |
| /// were granted. | |
| /// | |
| /// The scope strings will be separated by the provided [delimiter]. This | |
| /// defaults to `" "`, the OAuth2 standard, but some APIs (such as Facebook's) | |
| /// use non-standard delimiters. | |
| /// | |
| /// By default, this follows the OAuth2 spec and requires the server's responses | |
| /// to be in JSON format. However, some servers return non-standard response | |
| /// formats, which can be parsed using the [getParameters] function. | |
| /// | |
| /// This function is passed the `Content-Type` header of the response as well as | |
| /// its body as a UTF-8-decoded string. It should return a map in the same | |
| /// format as the [standard JSON response](https://tools.ietf.org/html/rfc6749#section-5.1) | |
| Future<Client> clientCredentialsGrant( | |
| Uri authorizationEndpoint, String? identifier, String? secret, | |
| {Iterable<String>? scopes, | |
| bool basicAuth = true, | |
| http.Client? httpClient, | |
| String? delimiter, | |
| Map<String, dynamic> Function(MediaType? contentType, String body)? | |
| getParameters}) async { | |
| delimiter ??= ' '; | |
| var startTime = DateTime.now(); | |
| var body = {'grant_type': 'client_credentials'}; | |
| var headers = <String, String>{}; | |
| if (identifier != null) { | |
| if (basicAuth) { | |
| headers['Authorization'] = basicAuthHeader(identifier, secret!); | |
| } else { | |
| body['client_id'] = identifier; | |
| if (secret != null) body['client_secret'] = secret; | |
| } | |
| } | |
| if (scopes != null && scopes.isNotEmpty) { | |
| body['scope'] = scopes.join(delimiter); | |
| } | |
| httpClient ??= http.Client(); | |
| var response = await httpClient.post(authorizationEndpoint, | |
| headers: headers, body: body); | |
| var credentials = handleAccessTokenResponse(response, authorizationEndpoint, | |
| startTime, scopes?.toList() ?? [], delimiter, | |
| getParameters: getParameters); | |
| return Client(credentials, | |
| identifier: identifier, secret: secret, httpClient: httpClient); | |
| } |