@@ -9,163 +9,161 @@ const revokeGrant = require('../../helpers/revoke_grant');
9
9
10
10
const gty = 'authorization_code' ;
11
11
12
- module . exports . handler = function getAuthorizationCodeHandler ( provider ) {
12
+ module . exports . handler = async function authorizationCodeHandler ( ctx , next ) {
13
13
const {
14
14
issueRefreshToken,
15
15
audiences,
16
16
conformIdTokenClaims,
17
- } = instance ( provider ) . configuration ( ) ;
18
-
19
- return async function authorizationCodeResponse ( ctx , next ) {
20
- if ( ctx . oidc . params . redirect_uri === undefined ) {
21
- // It is permitted to omit the redirect_uri if only ONE is registered on the client
22
- const { 0 : uri , length } = ctx . oidc . client . redirectUris ;
23
- if ( uri && length === 1 ) {
24
- ctx . oidc . params . redirect_uri = uri ;
25
- }
17
+ } = instance ( ctx . oidc . provider ) . configuration ( ) ;
18
+
19
+ if ( ctx . oidc . params . redirect_uri === undefined ) {
20
+ // It is permitted to omit the redirect_uri if only ONE is registered on the client
21
+ const { 0 : uri , length } = ctx . oidc . client . redirectUris ;
22
+ if ( uri && length === 1 ) {
23
+ ctx . oidc . params . redirect_uri = uri ;
26
24
}
25
+ }
27
26
28
- presence ( ctx , 'code' , 'redirect_uri' ) ;
27
+ presence ( ctx , 'code' , 'redirect_uri' ) ;
29
28
30
- const code = await provider . AuthorizationCode . find ( ctx . oidc . params . code , {
31
- ignoreExpiration : true ,
32
- } ) ;
29
+ const code = await ctx . oidc . provider . AuthorizationCode . find ( ctx . oidc . params . code , {
30
+ ignoreExpiration : true ,
31
+ } ) ;
33
32
34
- if ( ! code ) {
35
- throw new InvalidGrant ( 'authorization code not found' ) ;
36
- }
33
+ if ( ! code ) {
34
+ throw new InvalidGrant ( 'authorization code not found' ) ;
35
+ }
37
36
38
- uidToGrantId ( 'switched from uid=%s to value of grantId=%s' , ctx . oidc . uid , code . grantId ) ;
39
- ctx . oidc . uid = code . grantId ;
37
+ uidToGrantId ( 'switched from uid=%s to value of grantId=%s' , ctx . oidc . uid , code . grantId ) ;
38
+ ctx . oidc . uid = code . grantId ;
40
39
41
- if ( code . isExpired ) {
42
- throw new InvalidGrant ( 'authorization code is expired' ) ;
43
- }
40
+ if ( code . isExpired ) {
41
+ throw new InvalidGrant ( 'authorization code is expired' ) ;
42
+ }
44
43
45
- checkPKCE ( ctx . oidc . params . code_verifier , code . codeChallenge , code . codeChallengeMethod ) ;
44
+ checkPKCE ( ctx . oidc . params . code_verifier , code . codeChallenge , code . codeChallengeMethod ) ;
46
45
47
- if ( code . clientId !== ctx . oidc . client . clientId ) {
48
- throw new InvalidGrant ( 'authorization code client mismatch' ) ;
49
- }
46
+ if ( code . clientId !== ctx . oidc . client . clientId ) {
47
+ throw new InvalidGrant ( 'authorization code client mismatch' ) ;
48
+ }
50
49
51
- if ( code . consumed ) {
52
- await Promise . all ( [
53
- code . destroy ( ) ,
54
- revokeGrant ( provider , ctx . oidc . client , code . grantId ) ,
55
- ] ) ;
56
- provider . emit ( 'grant.revoked' , ctx , code . grantId ) ;
57
- throw new InvalidGrant ( 'authorization code already consumed' ) ;
58
- }
50
+ if ( code . consumed ) {
51
+ await Promise . all ( [
52
+ code . destroy ( ) ,
53
+ revokeGrant ( ctx . oidc . provider , ctx . oidc . client , code . grantId ) ,
54
+ ] ) ;
55
+ ctx . oidc . provider . emit ( 'grant.revoked' , ctx , code . grantId ) ;
56
+ throw new InvalidGrant ( 'authorization code already consumed' ) ;
57
+ }
59
58
60
- await code . consume ( ) ;
59
+ await code . consume ( ) ;
61
60
62
- if ( code . redirectUri !== ctx . oidc . params . redirect_uri ) {
63
- throw new InvalidGrant ( 'authorization code redirect_uri mismatch' ) ;
64
- }
61
+ if ( code . redirectUri !== ctx . oidc . params . redirect_uri ) {
62
+ throw new InvalidGrant ( 'authorization code redirect_uri mismatch' ) ;
63
+ }
64
+
65
+ ctx . oidc . entity ( 'AuthorizationCode' , code ) ;
66
+
67
+ const account = await ctx . oidc . provider . Account . findById ( ctx , code . accountId , code ) ;
65
68
66
- ctx . oidc . entity ( 'AuthorizationCode' , code ) ;
69
+ if ( ! account ) {
70
+ throw new InvalidGrant ( 'authorization code invalid (referenced account not found)' ) ;
71
+ }
72
+ ctx . oidc . entity ( 'Account' , account ) ;
67
73
68
- const account = await provider . Account . findById ( ctx , code . accountId , code ) ;
74
+ const { AccessToken, IdToken, RefreshToken } = ctx . oidc . provider ;
75
+ const at = new AccessToken ( {
76
+ accountId : account . accountId ,
77
+ claims : code . claims ,
78
+ client : ctx . oidc . client ,
79
+ expiresWithSession : code . expiresWithSession ,
80
+ grantId : code . grantId ,
81
+ gty,
82
+ scope : code . scope ,
83
+ sessionUid : code . sessionUid ,
84
+ sid : code . sid ,
85
+ } ) ;
69
86
70
- if ( ! account ) {
71
- throw new InvalidGrant ( 'authorization code invalid (referenced account not found)' ) ;
87
+ if ( ctx . oidc . client . tlsClientCertificateBoundAccessTokens ) {
88
+ const cert = ctx . get ( 'x-ssl-client-cert' ) ;
89
+
90
+ if ( ! cert ) {
91
+ throw new InvalidGrant ( 'mutual TLS client certificate missing' ) ;
72
92
}
73
- ctx . oidc . entity ( 'Account' , account ) ;
93
+ at . setS256Thumbprint ( cert ) ;
94
+ }
95
+
96
+ at . setAudiences ( await audiences ( ctx , account . accountId , at , 'access_token' ) ) ;
74
97
75
- const { AccessToken, IdToken, RefreshToken } = provider ;
76
- const at = new AccessToken ( {
98
+ ctx . oidc . entity ( 'AccessToken' , at ) ;
99
+ const accessToken = await at . save ( ) ;
100
+
101
+ let refreshToken ;
102
+ if ( await issueRefreshToken ( ctx , ctx . oidc . client , code ) ) {
103
+ const rt = new RefreshToken ( {
77
104
accountId : account . accountId ,
105
+ acr : code . acr ,
106
+ amr : code . amr ,
107
+ authTime : code . authTime ,
78
108
claims : code . claims ,
79
109
client : ctx . oidc . client ,
80
110
expiresWithSession : code . expiresWithSession ,
81
111
grantId : code . grantId ,
82
112
gty,
113
+ nonce : code . nonce ,
114
+ resource : code . resource ,
83
115
scope : code . scope ,
84
116
sessionUid : code . sessionUid ,
85
117
sid : code . sid ,
86
118
} ) ;
87
119
88
- if ( ctx . oidc . client . tlsClientCertificateBoundAccessTokens ) {
120
+ if ( ctx . oidc . client . tlsClientCertificateBoundAccessTokens && ctx . oidc . client . tokenEndpointAuthMethod === 'none' ) {
89
121
const cert = ctx . get ( 'x-ssl-client-cert' ) ;
90
-
91
- if ( ! cert ) {
92
- throw new InvalidGrant ( 'mutual TLS client certificate missing' ) ;
93
- }
94
- at . setS256Thumbprint ( cert ) ;
122
+ // cert presence is already checked in the access token block
123
+ rt . setS256Thumbprint ( cert ) ;
95
124
}
96
125
97
- at . setAudiences ( await audiences ( ctx , account . accountId , at , 'access_token' ) ) ;
98
-
99
- ctx . oidc . entity ( 'AccessToken' , at ) ;
100
- const accessToken = await at . save ( ) ;
101
-
102
- let refreshToken ;
103
- if ( await issueRefreshToken ( ctx , ctx . oidc . client , code ) ) {
104
- const rt = new RefreshToken ( {
105
- accountId : account . accountId ,
106
- acr : code . acr ,
107
- amr : code . amr ,
108
- authTime : code . authTime ,
109
- claims : code . claims ,
110
- client : ctx . oidc . client ,
111
- expiresWithSession : code . expiresWithSession ,
112
- grantId : code . grantId ,
113
- gty,
114
- nonce : code . nonce ,
115
- resource : code . resource ,
116
- scope : code . scope ,
117
- sessionUid : code . sessionUid ,
118
- sid : code . sid ,
119
- } ) ;
120
-
121
- if ( ctx . oidc . client . tlsClientCertificateBoundAccessTokens && ctx . oidc . client . tokenEndpointAuthMethod === 'none' ) {
122
- const cert = ctx . get ( 'x-ssl-client-cert' ) ;
123
- // cert presence is already checked in the access token block
124
- rt . setS256Thumbprint ( cert ) ;
125
- }
126
-
127
- ctx . oidc . entity ( 'RefreshToken' , rt ) ;
128
- refreshToken = await rt . save ( ) ;
126
+ ctx . oidc . entity ( 'RefreshToken' , rt ) ;
127
+ refreshToken = await rt . save ( ) ;
128
+ }
129
+
130
+ let idToken ;
131
+ if ( code . scopes . has ( 'openid' ) ) {
132
+ const claims = get ( code , 'claims.id_token' , { } ) ;
133
+ const rejected = get ( code , 'claims.rejected' , [ ] ) ;
134
+ const token = new IdToken ( {
135
+ ...await account . claims ( 'id_token' , code . scope , claims , rejected ) ,
136
+ acr : code . acr ,
137
+ amr : code . amr ,
138
+ auth_time : code . authTime ,
139
+ } , { ctx } ) ;
140
+
141
+ if ( conformIdTokenClaims ) {
142
+ token . scope = 'openid' ;
143
+ } else {
144
+ token . scope = code . scope ;
129
145
}
130
146
131
- let idToken ;
132
- if ( code . scopes . has ( 'openid' ) ) {
133
- const claims = get ( code , 'claims.id_token' , { } ) ;
134
- const rejected = get ( code , 'claims.rejected' , [ ] ) ;
135
- const token = new IdToken ( {
136
- ...await account . claims ( 'id_token' , code . scope , claims , rejected ) ,
137
- acr : code . acr ,
138
- amr : code . amr ,
139
- auth_time : code . authTime ,
140
- } , { ctx } ) ;
141
-
142
- if ( conformIdTokenClaims ) {
143
- token . scope = 'openid' ;
144
- } else {
145
- token . scope = code . scope ;
146
- }
147
-
148
- token . mask = claims ;
149
- token . rejected = rejected ;
150
-
151
- token . set ( 'nonce' , code . nonce ) ;
152
- token . set ( 'at_hash' , accessToken ) ;
153
- token . set ( 'sid' , code . sid ) ;
154
-
155
- idToken = await token . sign ( ) ;
156
- }
147
+ token . mask = claims ;
148
+ token . rejected = rejected ;
157
149
158
- ctx . body = {
159
- access_token : accessToken ,
160
- expires_in : at . expiration ,
161
- id_token : idToken ,
162
- refresh_token : refreshToken ,
163
- scope : code . scope ,
164
- token_type : 'Bearer' ,
165
- } ;
150
+ token . set ( 'nonce' , code . nonce ) ;
151
+ token . set ( 'at_hash' , accessToken ) ;
152
+ token . set ( 'sid' , code . sid ) ;
166
153
167
- await next ( ) ;
154
+ idToken = await token . sign ( ) ;
155
+ }
156
+
157
+ ctx . body = {
158
+ access_token : accessToken ,
159
+ expires_in : at . expiration ,
160
+ id_token : idToken ,
161
+ refresh_token : refreshToken ,
162
+ scope : code . scope ,
163
+ token_type : 'Bearer' ,
168
164
} ;
165
+
166
+ await next ( ) ;
169
167
} ;
170
168
171
169
module . exports . parameters = new Set ( [ 'code' , 'redirect_uri' ] ) ;
0 commit comments