mod_http_oauth2/mod_http_oauth2.lua
changeset 5261 b2120fb4a279
parent 5260 44f7edd4f845
child 5262 9629971e307f
equal deleted inserted replaced
5260:44f7edd4f845 5261:b2120fb4a279
   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