150 -- client needs to be revoked |
150 -- client needs to be revoked |
151 local function client_subset(client) |
151 local function client_subset(client) |
152 return { name = client.client_name; uri = client.client_uri }; |
152 return { name = client.client_name; uri = client.client_uri }; |
153 end |
153 end |
154 |
154 |
155 local function new_access_token(token_jid, role, scope, ttl, client) |
155 local function new_access_token(token_jid, role, scope, ttl, client, id_token) |
156 local token_data = {}; |
156 local token_data = {}; |
157 if client then |
157 if client then |
158 token_data.oauth2_client = client_subset(client); |
158 token_data.oauth2_client = client_subset(client); |
159 end |
159 end |
160 if next(token_data) == nil then |
160 if next(token_data) == nil then |
164 return { |
164 return { |
165 token_type = "bearer"; |
165 token_type = "bearer"; |
166 access_token = token; |
166 access_token = token; |
167 expires_in = ttl; |
167 expires_in = ttl; |
168 scope = scope; |
168 scope = scope; |
|
169 id_token = id_token; |
169 -- TODO: include refresh_token when implemented |
170 -- TODO: include refresh_token when implemented |
170 }; |
171 }; |
171 end |
172 end |
172 |
173 |
173 local function get_redirect_uri(client, query_redirect_uri) -- record client, string : string |
174 local function get_redirect_uri(client, query_redirect_uri) -- record client, string : string |
202 return oauth_error("invalid_grant", "incorrect credentials"); |
203 return oauth_error("invalid_grant", "incorrect credentials"); |
203 end |
204 end |
204 |
205 |
205 local granted_jid = jid.join(request_username, request_host, request_resource); |
206 local granted_jid = jid.join(request_username, request_host, request_resource); |
206 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
207 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
207 return json.encode(new_access_token(granted_jid, granted_role, granted_scopes, nil)); |
208 return json.encode(new_access_token(granted_jid, granted_role, granted_scopes, nil, nil)); |
208 end |
209 end |
209 |
210 |
210 function response_type_handlers.code(client, params, granted_jid) |
211 function response_type_handlers.code(client, params, granted_jid, id_token) |
211 local request_username, request_host = jid.split(granted_jid); |
212 local request_username, request_host = jid.split(granted_jid); |
212 if not request_host or request_host ~= module.host then |
213 if not request_host or request_host ~= module.host then |
213 return oauth_error("invalid_request", "invalid JID"); |
214 return oauth_error("invalid_request", "invalid JID"); |
214 end |
215 end |
215 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
216 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
218 local ok = codes:set(params.client_id .. "#" .. code, { |
219 local ok = codes:set(params.client_id .. "#" .. code, { |
219 expires = os.time() + 600; |
220 expires = os.time() + 600; |
220 granted_jid = granted_jid; |
221 granted_jid = granted_jid; |
221 granted_scopes = granted_scopes; |
222 granted_scopes = granted_scopes; |
222 granted_role = granted_role; |
223 granted_role = granted_role; |
|
224 id_token = id_token; |
223 }); |
225 }); |
224 if not ok then |
226 if not ok then |
225 return {status_code = 429}; |
227 return {status_code = 429}; |
226 end |
228 end |
227 |
229 |
266 local request_username, request_host = jid.split(granted_jid); |
268 local request_username, request_host = jid.split(granted_jid); |
267 if not request_host or request_host ~= module.host then |
269 if not request_host or request_host ~= module.host then |
268 return oauth_error("invalid_request", "invalid JID"); |
270 return oauth_error("invalid_request", "invalid JID"); |
269 end |
271 end |
270 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
272 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
271 local token_info = new_access_token(granted_jid, granted_role, granted_scopes, nil, client); |
273 local token_info = new_access_token(granted_jid, granted_role, granted_scopes, nil, client, nil); |
272 |
274 |
273 local redirect = url.parse(get_redirect_uri(client, params.redirect_uri)); |
275 local redirect = url.parse(get_redirect_uri(client, params.redirect_uri)); |
274 token_info.state = params.state; |
276 token_info.state = params.state; |
275 redirect.fragment = http.formencode(token_info); |
277 redirect.fragment = http.formencode(token_info); |
276 |
278 |
315 if not code or type(code) ~= "table" or code_expired(code) then |
317 if not code or type(code) ~= "table" or code_expired(code) then |
316 module:log("debug", "authorization_code invalid or expired: %q", code); |
318 module:log("debug", "authorization_code invalid or expired: %q", code); |
317 return oauth_error("invalid_client", "incorrect credentials"); |
319 return oauth_error("invalid_client", "incorrect credentials"); |
318 end |
320 end |
319 |
321 |
320 return json.encode(new_access_token(code.granted_jid, code.granted_role, code.granted_scopes, nil, client)); |
322 return json.encode(new_access_token(code.granted_jid, code.granted_role, code.granted_scopes, nil, client, code.id_token)); |
321 end |
323 end |
322 |
324 |
323 -- Used to issue/verify short-lived tokens for the authorization process below |
325 -- Used to issue/verify short-lived tokens for the authorization process below |
324 local new_user_token, verify_user_token = jwt.init("HS256", random.bytes(32), nil, { default_ttl = 600 }); |
326 local new_user_token, verify_user_token = jwt.init("HS256", random.bytes(32), nil, { default_ttl = 600 }); |
325 |
327 |
547 elseif not auth_state.consent then |
549 elseif not auth_state.consent then |
548 -- Notify client of rejection |
550 -- Notify client of rejection |
549 return error_response(request, oauth_error("access_denied")); |
551 return error_response(request, oauth_error("access_denied")); |
550 end |
552 end |
551 |
553 |
|
554 local user_jid = jid.join(auth_state.user.username, module.host); |
|
555 local client_secret = make_secret(params.client_id); |
|
556 local id_token_signer = jwt.new_signer("HS256", client_secret); |
|
557 local id_token = id_token_signer({ |
|
558 iss = get_issuer(); |
|
559 sub = url.build({ scheme = "xmpp"; path = user_jid }); |
|
560 aud = params.client_id; |
|
561 nonce = params.nonce; |
|
562 }); |
552 local response_type = params.response_type; |
563 local response_type = params.response_type; |
553 local response_handler = response_type_handlers[response_type]; |
564 local response_handler = response_type_handlers[response_type]; |
554 if not response_handler then |
565 if not response_handler then |
555 return error_response(request, oauth_error("unsupported_response_type")); |
566 return error_response(request, oauth_error("unsupported_response_type")); |
556 end |
567 end |
557 return response_handler(client, params, jid.join(auth_state.user.username, module.host)); |
568 return response_handler(client, params, user_jid, id_token); |
558 end |
569 end |
559 |
570 |
560 local function handle_revocation_request(event) |
571 local function handle_revocation_request(event) |
561 local request, response = event.request, event.response; |
572 local request, response = event.request, event.response; |
562 if not request.headers.authorization then |
573 if not request.headers.authorization then |