Use POST+Redirect_with_cookie

(cherry picked from commit 69b54869c9)
This commit is contained in:
Marcial Rosales 2025-03-12 16:47:33 +01:00 committed by Mergify
parent 7e374043be
commit 5e5521a3c0
4 changed files with 77 additions and 24 deletions

View File

@ -13,3 +13,6 @@
-define(MANAGEMENT_PG_GROUP, management_db).
-define(MANAGEMENT_DEFAULT_HTTP_MAX_BODY_SIZE, 20000000).
-define(OAUTH2_ACCESS_TOKEN_COOKIE_NAME, <<"access_token">>).
-define(OAUTH2_ACCESS_TOKEN_COOKIE_PATH, <<"/js/oidc-oauth/bootstrap.js">>).

View File

@ -10,29 +10,52 @@
-export([init/2]).
-include_lib("rabbitmq_management_agent/include/rabbit_mgmt_records.hrl").
-include("rabbit_mgmt.hrl").
%%--------------------------------------------------------------------
init(Req0, State) ->
login(cowboy_req:method(Req0), Req0, State).
login(<<"POST">>, Req0, State) ->
login(<<"POST">>, Req0=#{scheme := Scheme}, State) ->
{ok, Body, _} = cowboy_req:read_urlencoded_body(Req0),
AccessToken = proplists:get_value(<<"access_token">>, Body),
case rabbit_mgmt_util:is_authorized_user(Req0, #context{}, <<"">>, AccessToken, false) of
{true, Req1, _} ->
NewBody = ["<html><head></head><body><script src='js/prefs.js'></script><script type='text/javascript'>",
"set_token_auth('", AccessToken, "'); window.location = '", rabbit_mgmt_util:get_path_prefix(),
"/'</script></body></html>"],
Req2 = cowboy_req:reply(200, #{<<"content-type">> => <<"text/html; charset=utf-8">>}, NewBody, Req1),
{ok, Req2, State};
CookieSettings = #{
http_only => true,
path => ?OAUTH2_ACCESS_TOKEN_COOKIE_PATH,
max_age => 30,
same_site => strict
},
SetCookie = cowboy_req:set_resp_cookie(?OAUTH2_ACCESS_TOKEN_COOKIE_NAME, AccessToken, Req1,
case Scheme of
<<"https">> -> CookieSettings#{ secure => true};
_ -> CookieSettings
end),
Home = cowboy_req:uri(SetCookie, #{
path => rabbit_mgmt_util:get_path_prefix() ++ "/"
}),
Redirect = cowboy_req:reply(302, #{
<<"Location">> => iolist_to_binary(Home)
}, <<>>, SetCookie),
{ok, Redirect, State};
{false, ReqData1, Reason} ->
Home = cowboy_req:uri(ReqData1, #{path => rabbit_mgmt_util:get_path_prefix() ++ "/", qs => "error=" ++ Reason}),
ReqData2 = cowboy_req:reply(302,
#{<<"Location">> => iolist_to_binary(Home) },
<<>>, ReqData1),
{ok, ReqData2, State}
replyWithError(Reason, ReqData1, State)
end;
login(_, Req0, State) ->
%% Method not allowed.
{ok, cowboy_req:reply(405, Req0), State}.
replyWithError(Reason, Req, State) ->
Home = cowboy_req:uri(Req, #{
path => rabbit_mgmt_util:get_path_prefix() ++ "/",
qs => "error=" ++ Reason
}),
Req2 = cowboy_req:reply(302, #{
<<"Location">> => iolist_to_binary(Home)
}, <<>>, Req),
{ok, Req2, State}.

View File

@ -8,6 +8,7 @@
-module(rabbit_mgmt_oauth_bootstrap).
-export([init/2]).
-include("rabbit_mgmt.hrl").
%%--------------------------------------------------------------------
@ -18,12 +19,14 @@ init(Req0, State) ->
bootstrap_oauth(Req0, State) ->
AuthSettings = rabbit_mgmt_wm_auth:authSettings(),
Dependencies = oauth_dependencies(),
{Req1, SetTokenAuth} = set_token_auth(AuthSettings, Req0),
JSContent = import_dependencies(Dependencies) ++
set_oauth_settings(AuthSettings) ++
set_token_auth(AuthSettings, Req0) ++
SetTokenAuth ++
export_dependencies(Dependencies),
{ok, cowboy_req:reply(200, #{<<"content-type">> => <<"text/javascript; charset=utf-8">>},
JSContent, Req0), State}.
JSContent, Req1), State}.
set_oauth_settings(AuthSettings) ->
JsonAuthSettings = rabbit_json:encode(rabbit_mgmt_format:format_nulls(AuthSettings)),
@ -33,11 +36,35 @@ set_token_auth(AuthSettings, Req0) ->
case proplists:get_value(oauth_enabled, AuthSettings, false) of
true ->
case cowboy_req:parse_header(<<"authorization">>, Req0) of
{bearer, Token} -> ["set_token_auth('", Token, "');"];
_ -> []
end;
false ->
{bearer, Token} ->
{
Req0,
["set_token_auth('", Token, "');"]
};
_ ->
Cookies = cowboy_req:parse_cookies(Req0),
case lists:keyfind(?OAUTH2_ACCESS_TOKEN_COOKIE_NAME, 1, Cookies) of
{_, Token} ->
{
cowboy_req:set_resp_cookie(
?OAUTH2_ACCESS_TOKEN_COOKIE_NAME, <<"">>, Req0, #{
max_age => 0,
http_only => true,
path => ?OAUTH2_ACCESS_TOKEN_COOKIE_PATH,
same_site => strict
}),
["set_token_auth('", Token, "');"]
};
false -> {
Req0,
[]
}
end
end;
false -> {
Req0,
[]
}
end.
import_dependencies(Dependencies) ->

View File

@ -52,7 +52,7 @@ start_fakeportal() {
--env CLIENT_ID="${CLIENT_ID}" \
--env CLIENT_SECRET="${CLIENT_SECRET}" \
--env NODE_EXTRA_CA_CERTS=/etc/uaa/ca_uaa_certificate.pem \
-v ${TEST_CONFIG_PATH}/uaa:/etc/uaa \
-v ${TEST_CONFIG_DIR}/uaa:/etc/uaa \
-v ${FAKEPORTAL_DIR}:/code/fakeportal \
mocha-test:${mocha_test_tag} run fakeportal