| // 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. |
| |
| library authorization_code_grant_test; |
| |
| import 'dart:async'; |
| import 'dart:convert'; |
| |
| import 'package:unittest/unittest.dart'; |
| import 'package:http/http.dart' as http; |
| import 'package:oauth2/oauth2.dart' as oauth2; |
| |
| import 'utils.dart'; |
| |
| final redirectUrl = Uri.parse('http://example.com/redirect'); |
| |
| ExpectClient client; |
| |
| oauth2.AuthorizationCodeGrant grant; |
| |
| void createGrant() { |
| client = new ExpectClient(); |
| grant = new oauth2.AuthorizationCodeGrant( |
| 'identifier', |
| 'secret', |
| Uri.parse('https://example.com/authorization'), |
| Uri.parse('https://example.com/token'), |
| httpClient: client); |
| } |
| |
| void expectFutureThrows(future, predicate) { |
| future.catchError(expectAsync1((error) { |
| expect(predicate(error), isTrue); |
| })); |
| } |
| |
| void main() { |
| group('.getAuthorizationUrl', () { |
| setUp(createGrant); |
| |
| test('builds the correct URL', () { |
| expect(grant.getAuthorizationUrl(redirectUrl).toString(), |
| equals('https://example.com/authorization' |
| '?response_type=code' |
| '&client_id=identifier' |
| '&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect')); |
| }); |
| |
| test('builds the correct URL with scopes', () { |
| var authorizationUrl = grant.getAuthorizationUrl( |
| redirectUrl, scopes: ['scope', 'other/scope']); |
| expect(authorizationUrl.toString(), |
| equals('https://example.com/authorization' |
| '?response_type=code' |
| '&client_id=identifier' |
| '&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect' |
| '&scope=scope+other%2Fscope')); |
| }); |
| |
| test('builds the correct URL with state', () { |
| var authorizationUrl = grant.getAuthorizationUrl( |
| redirectUrl, state: 'state'); |
| expect(authorizationUrl.toString(), |
| equals('https://example.com/authorization' |
| '?response_type=code' |
| '&client_id=identifier' |
| '&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect' |
| '&state=state')); |
| }); |
| |
| test('merges with existing query parameters', () { |
| grant = new oauth2.AuthorizationCodeGrant( |
| 'identifier', |
| 'secret', |
| Uri.parse('https://example.com/authorization?query=value'), |
| Uri.parse('https://example.com/token'), |
| httpClient: client); |
| |
| var authorizationUrl = grant.getAuthorizationUrl(redirectUrl); |
| expect(authorizationUrl.toString(), |
| equals('https://example.com/authorization' |
| '?query=value' |
| '&response_type=code' |
| '&client_id=identifier' |
| '&redirect_uri=http%3A%2F%2Fexample.com%2Fredirect')); |
| }); |
| |
| test("can't be called twice", () { |
| grant.getAuthorizationUrl(redirectUrl); |
| expect(() => grant.getAuthorizationUrl(redirectUrl), throwsStateError); |
| }); |
| }); |
| |
| group('.handleAuthorizationResponse', () { |
| setUp(createGrant); |
| |
| test("can't be called before .getAuthorizationUrl", () { |
| expectFutureThrows(grant.handleAuthorizationResponse({}), |
| (e) => e is StateError); |
| }); |
| |
| test("can't be called twice", () { |
| grant.getAuthorizationUrl(redirectUrl); |
| expectFutureThrows( |
| grant.handleAuthorizationResponse({'code': 'auth code'}), |
| (e) => e is FormatException); |
| expectFutureThrows( |
| grant.handleAuthorizationResponse({'code': 'auth code'}), |
| (e) => e is StateError); |
| }); |
| |
| test('must have a state parameter if the authorization URL did', () { |
| grant.getAuthorizationUrl(redirectUrl, state: 'state'); |
| expectFutureThrows( |
| grant.handleAuthorizationResponse({'code': 'auth code'}), |
| (e) => e is FormatException); |
| }); |
| |
| test('must have the same state parameter the authorization URL did', () { |
| grant.getAuthorizationUrl(redirectUrl, state: 'state'); |
| expectFutureThrows(grant.handleAuthorizationResponse({ |
| 'code': 'auth code', |
| 'state': 'other state' |
| }), (e) => e is FormatException); |
| }); |
| |
| test('must have a code parameter', () { |
| grant.getAuthorizationUrl(redirectUrl); |
| expectFutureThrows(grant.handleAuthorizationResponse({}), |
| (e) => e is FormatException); |
| }); |
| |
| test('with an error parameter throws an AuthorizationException', () { |
| grant.getAuthorizationUrl(redirectUrl); |
| expectFutureThrows( |
| grant.handleAuthorizationResponse({'error': 'invalid_request'}), |
| (e) => e is oauth2.AuthorizationException); |
| }); |
| |
| test('sends an authorization code request', () { |
| grant.getAuthorizationUrl(redirectUrl); |
| client.expectRequest((request) { |
| expect(request.method, equals('POST')); |
| expect(request.url.toString(), equals(grant.tokenEndpoint.toString())); |
| expect(request.bodyFields, equals({ |
| 'grant_type': 'authorization_code', |
| 'code': 'auth code', |
| 'redirect_uri': redirectUrl.toString(), |
| 'client_id': 'identifier', |
| 'client_secret': 'secret' |
| })); |
| |
| return new Future.value(new http.Response(JSON.encode({ |
| 'access_token': 'access token', |
| 'token_type': 'bearer', |
| }), 200, headers: {'content-type': 'application/json'})); |
| }); |
| |
| grant.handleAuthorizationResponse({'code': 'auth code'}) |
| .then(expectAsync1((client) { |
| expect(client.credentials.accessToken, equals('access token')); |
| })); |
| }); |
| }); |
| |
| group('.handleAuthorizationCode', () { |
| setUp(createGrant); |
| |
| test("can't be called before .getAuthorizationUrl", () { |
| expectFutureThrows( |
| grant.handleAuthorizationCode('auth code'), |
| (e) => e is StateError); |
| }); |
| |
| test("can't be called twice", () { |
| grant.getAuthorizationUrl(redirectUrl); |
| expectFutureThrows( |
| grant.handleAuthorizationCode('auth code'), |
| (e) => e is FormatException); |
| expectFutureThrows(grant.handleAuthorizationCode('auth code'), |
| (e) => e is StateError); |
| }); |
| |
| test('sends an authorization code request', () { |
| grant.getAuthorizationUrl(redirectUrl); |
| client.expectRequest((request) { |
| expect(request.method, equals('POST')); |
| expect(request.url.toString(), equals(grant.tokenEndpoint.toString())); |
| expect(request.bodyFields, equals({ |
| 'grant_type': 'authorization_code', |
| 'code': 'auth code', |
| 'redirect_uri': redirectUrl.toString(), |
| 'client_id': 'identifier', |
| 'client_secret': 'secret' |
| })); |
| |
| return new Future.value(new http.Response(JSON.encode({ |
| 'access_token': 'access token', |
| 'token_type': 'bearer', |
| }), 200, headers: {'content-type': 'application/json'})); |
| }); |
| |
| expect(grant.handleAuthorizationCode('auth code'), |
| completion(predicate((client) { |
| expect(client.credentials.accessToken, equals('access token')); |
| return true; |
| }))); |
| }); |
| }); |
| } |