|
1 | 1 | part of authenticationserver.router;
|
2 | 2 |
|
3 |
| -void oauthCallback(HttpRequest request) { |
4 |
| - try { |
5 |
| - //State is used as a return URL. |
6 |
| - String state = queryParameter(request.uri, 'state'); |
7 |
| - if(state == null) { |
8 |
| - serverError(request, 'authenticationserver.router.oauthCallback() State parameter is missing "${request.uri}"'); |
9 |
| - return; |
10 |
| - } |
11 |
| - Uri returnUrl = Uri.parse(state); |
12 |
| - Map postBody = |
13 |
| - { |
14 |
| - "grant_type": "authorization_code", |
15 |
| - "code": request.uri.queryParameters['code'], |
16 |
| - "redirect_uri": config.redirectUri.toString(), |
17 |
| - "client_id": config.clientId, |
18 |
| - "client_secret": config.clientSecret |
19 |
| - }; |
20 |
| - String body = mapToUrlFormEncodedPostBody(postBody); |
21 |
| - logger.debug('authenticationserver.router.oauthCallback() Sending request to google. "${tokenEndpoint}" body "${body}"'); |
22 |
| - |
23 |
| - //Now we have the "code" which will be exchanged to a token. |
24 |
| - http.post(tokenEndpoint, headers: {'content-type':'application/x-www-form-urlencoded'}, body: postBody) |
25 |
| - .then((http.Response response) { |
26 |
| - Map json = JSON.decode(response.body); |
27 |
| - |
28 |
| - if(json.containsKey('error')) { |
29 |
| - serverError(request, 'authenticationserver.router.oauthCallback() Authtication failed. "${json}"'); |
| 3 | +Future<shelf.Response> oauthCallback(shelf.Request request) { |
| 4 | + final String stateString = request.url.queryParameters.containsKey('state') |
| 5 | + ? request.url.queryParameters['state'] |
| 6 | + : ''; |
30 | 7 |
|
31 |
| - } else { |
32 |
| - json['expiresAt'] = dateTimeToJson(new DateTime.now().add(config.tokenexpiretime)); |
33 |
| - return getUserInfo(json['access_token']).then((Map userData) { |
34 |
| - if(userData == null || userData.isEmpty) { |
35 |
| - logger.debug('authenticationserver.router.oauthCallback() token:"${json['access_token']}" userdata:"${userData}"'); |
36 |
| - request.response.statusCode = 403; |
37 |
| - writeAndClose(request, JSON.encode({'status': 'Forbidden!'})); |
38 |
| - |
39 |
| - } else { |
40 |
| - json['identity'] = userData; |
41 |
| - |
42 |
| - String cacheObject = JSON.encode(json); |
43 |
| - String hash = Sha256Token(cacheObject); |
44 |
| - |
45 |
| - try { |
46 |
| - vault.insertToken(hash, json); |
47 |
| - Map queryParameters = {'settoken' : hash}; |
48 |
| - request.response.redirect(new Uri( |
49 |
| - scheme: returnUrl.scheme, |
50 |
| - userInfo: returnUrl.userInfo, |
51 |
| - host: returnUrl.host, |
52 |
| - port: returnUrl.port, |
53 |
| - path: returnUrl.path, |
54 |
| - queryParameters: queryParameters)); |
55 |
| - |
56 |
| - } catch(error) { |
57 |
| - serverError(request, 'authenticationserver.router.oauthCallback uri ${request.uri} error: "${error}" data: "$json"'); |
58 |
| - } |
| 8 | + if (stateString.isEmpty) { |
| 9 | + return new Future.value(new shelf.Response.internalServerError( |
| 10 | + body: 'State parameter is missing "${request.url}"')); |
| 11 | + } |
| 12 | + |
| 13 | + log.finest('stateString:$stateString'); |
| 14 | + |
| 15 | + |
| 16 | + final Uri returnUrl = Uri.parse(stateString); |
| 17 | + final Map postBody = { |
| 18 | + "grant_type": "authorization_code", |
| 19 | + "code": request.url.queryParameters['code'], |
| 20 | + "redirect_uri": config.redirectUri.toString(), |
| 21 | + "client_id": config.clientId, |
| 22 | + "client_secret": config.clientSecret |
| 23 | + }; |
| 24 | + |
| 25 | + log.finest( |
| 26 | + 'Sending request to google. "${tokenEndpoint}" body "${postBody}"'); |
| 27 | + |
| 28 | + //Now we have the "code" which will be exchanged to a token. |
| 29 | + return httpClient.postForm(tokenEndpoint, postBody).then((String response) { |
| 30 | + Map json = JSON.decode(response); |
| 31 | + |
| 32 | + if (json.containsKey('error')) { |
| 33 | + return new shelf.Response.internalServerError( |
| 34 | + body: 'authenticationserver.router.oauthCallback() ' |
| 35 | + 'Authentication failed. "${json}"'); |
| 36 | + } else { |
| 37 | + ///FIXME: Change to use format from framework AND update the dummy tokens. |
| 38 | + json['expiresAt'] = |
| 39 | + new DateTime.now().add(config.tokenexpiretime).toString(); |
| 40 | + return getUserInfo(json['access_token']).then((Map userData) { |
| 41 | + if (userData == null || userData.isEmpty) { |
| 42 | + log.finest('authenticationserver.router.oauthCallback() ' |
| 43 | + 'token:"${json['access_token']}" userdata:"${userData}"'); |
| 44 | + |
| 45 | + return new shelf.Response.forbidden( |
| 46 | + JSON.encode(const {'status': 'Forbidden'})); |
| 47 | + } else { |
| 48 | + json['identity'] = userData; |
| 49 | + |
| 50 | + String cacheObject = JSON.encode(json); |
| 51 | + String hash = Sha256Token(cacheObject); |
| 52 | + |
| 53 | + try { |
| 54 | + vault.insertToken(hash, json); |
| 55 | + Map queryParameters = {'settoken': hash}; |
| 56 | + |
| 57 | + return new shelf.Response.found(new Uri( |
| 58 | + scheme: returnUrl.scheme, |
| 59 | + userInfo: returnUrl.userInfo, |
| 60 | + host: returnUrl.host, |
| 61 | + port: returnUrl.port, |
| 62 | + path: returnUrl.path, |
| 63 | + queryParameters: queryParameters)); |
| 64 | + } catch (error, stackTrace) { |
| 65 | + log.severe(error, stackTrace); |
| 66 | + |
| 67 | + return new shelf.Response.internalServerError( |
| 68 | + body: 'authenticationserver.router.oauthCallback ' |
| 69 | + 'uri ${request.url} error: "${error}" data: "$json"'); |
59 | 70 | }
|
60 |
| - }).catchError((error) { |
61 |
| - logger.error('authenticationserver.router.oauthCallback() requested userInfo error "${error}"'); |
62 |
| - request.response.statusCode = 403; |
63 |
| - writeAndClose(request, JSON.encode({'status': 'Forbidden.'})); |
64 |
| - }); |
65 |
| - } |
| 71 | + } |
| 72 | + }).catchError((error, stackTrace) { |
| 73 | + log.severe(error, stackTrace); |
| 74 | + return new shelf.Response.forbidden( |
| 75 | + JSON.encode(const {'status': 'Forbidden'})); |
| 76 | + }); |
| 77 | + } |
| 78 | + }).catchError((error, stackTrace) { |
| 79 | + log.severe(error, stackTrace); |
66 | 80 |
|
67 |
| - }).catchError((error) => serverError(request, 'authenticationserver.router.oauthCallback uri ${request.uri} error: "${error}"')); |
68 |
| - } catch(e) { |
69 |
| - serverError(request, 'authenticationserver.router.oauthCallback() error "${e}" Url "${request.uri}"'); |
70 |
| - } |
| 81 | + return new shelf.Response.internalServerError( |
| 82 | + body: 'authenticationserver.router.oauthCallback uri ${request.url} error: "${error}"'); |
| 83 | + }); |
71 | 84 | }
|
72 | 85 |
|
73 | 86 | /**
|
74 | 87 | * Asks google for the user data, for the user bound to the [access_token].
|
75 | 88 | */
|
76 | 89 | Future<Map> getUserInfo(String access_token) {
|
77 |
| - String url = 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=${access_token}'; |
| 90 | + Uri url = Uri.parse('https://www.googleapis.com/oauth2/' |
| 91 | + 'v1/userinfo?alt=json&access_token=${access_token}'); |
78 | 92 |
|
79 |
| - return http.get(url).then((http.Response response) { |
80 |
| - Map googleProfile = JSON.decode(response.body); |
| 93 | + return httpClient.get(url).then((String response) { |
| 94 | + Map googleProfile = JSON.decode(response); |
81 | 95 | return db.getUser(googleProfile['email']).then((Map agent) {
|
82 |
| - if(agent.isNotEmpty) { |
| 96 | + if (agent.isNotEmpty) { |
83 | 97 | agent['remote_attributes'] = googleProfile;
|
84 | 98 | return agent;
|
85 | 99 | } else {
|
|
0 commit comments