1
- #include < library/cpp/json/json_reader.h>
2
1
#include < library/cpp/string_utils/base64/base64.h>
3
2
#include < ydb/library/actors/http/http.h>
3
+ #include < ydb/library/security/util.h>
4
4
#include < ydb/mvp/core/mvp_log.h>
5
+ #include < ydb/mvp/core/mvp_tokens.h>
5
6
#include " openid_connect.h"
6
7
#include " oidc_session_create.h"
7
- #include " oidc_settings .h"
8
+ #include " oidc_impersonate_start_page_nebius .h"
8
9
9
10
namespace NMVP {
10
11
namespace NOIDC {
11
12
12
13
THandlerImpersonateStart::THandlerImpersonateStart (const NActors::TActorId& sender,
13
- const NHttp::THttpIncomingRequestPtr& request,
14
- const NActors::TActorId& httpProxyId,
15
- const TOpenIdConnectSettings& settings)
14
+ const NHttp::THttpIncomingRequestPtr& request,
15
+ const NActors::TActorId& httpProxyId,
16
+ const TOpenIdConnectSettings& settings)
16
17
: Sender(sender)
17
18
, Request(request)
18
19
, HttpProxyId(httpProxyId)
19
20
, Settings(settings)
20
21
{}
21
22
23
+ TString THandlerImpersonateStart::DecodeToken (const TStringBuf& cookie, const NActors::TActorContext& ctx) {
24
+ TString token;
25
+ try {
26
+ Base64StrictDecode (cookie, token);
27
+ } catch (std::exception& e) {
28
+ LOG_DEBUG_S (ctx, EService::MVP, " Base64Decode " << cookie << " cookie: " << e.what ());
29
+ token.clear ();
30
+ }
31
+ return token;
32
+ }
33
+
22
34
void THandlerImpersonateStart::Bootstrap (const NActors::TActorContext& ctx) {
35
+ LOG_DEBUG_S (ctx, EService::MVP, " Start impersonation process" );
23
36
NHttp::TUrlParameters urlParameters (Request->URL );
24
- TString serviceAccountId = urlParameters[" service_accound_id " ];
37
+ TString serviceAccountId = urlParameters[" service_account_id " ];
25
38
26
39
NHttp::THeaders headers (Request->Headers );
27
- LOG_DEBUG_S (ctx, EService::MVP, " Start impersonation process" );
28
40
NHttp::TCookies cookies (headers.Get (" Cookie" ));
29
- TString sessionToken = DecodeToken (cookies, CreateNameSessionCookie (Settings.ClientId ));
30
41
31
- if (sessionToken && serviceAccountId) {
32
- RequestImpersonatedToken (sessionToken, serviceAccountId, ctx);
33
- } else {
42
+ TString sessionCookieName = CreateNameSessionCookie (Settings.ClientId );
43
+ TStringBuf sessionCookieValue = cookies.Get (sessionCookieName);
44
+ if (!sessionCookieValue.Empty ()) {
45
+ LOG_DEBUG_S (ctx, EService::MVP, " Using session cookie (" << sessionCookieName << " : " << NKikimr::MaskTicket (sessionCookieValue) << " )" );
46
+ }
47
+
48
+ TString sessionToken = DecodeToken (sessionCookieValue, ctx);
49
+
50
+ TString jsonError;
51
+ if (sessionToken.empty ()) {
52
+ jsonError = " Wrong impersonate parameter: session cookie not found" ;
53
+ } else if (serviceAccountId.empty ()) {
54
+ jsonError = " Wrong impersonate parameter: account_id not found" ;
55
+ }
56
+
57
+ if (jsonError) {
34
58
NHttp::THeadersBuilder responseHeaders;
35
59
responseHeaders.Set (" Content-Type" , " text/plain" );
36
- httpResponse = Request->CreateResponse (" 400" , " Bad Request" , responseHeaders, event->Get ()->Error );
60
+ SetCORS (Request, &responseHeaders);
61
+ NHttp::THttpOutgoingResponsePtr httpResponse = Request->CreateResponse (" 400" , " Bad Request" , responseHeaders, jsonError);
62
+ ctx.Send (Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse (httpResponse));
63
+ Die (ctx);
64
+ } else {
65
+ RequestImpersonatedToken (sessionToken, serviceAccountId, ctx);
37
66
}
38
67
}
39
68
40
- void THandlerImpersonateStart::RequestImpersonatedToken (const TString sessionToken, const TString serviceAccountId, const NActors::TActorContext& ctx) {
69
+ void THandlerImpersonateStart::RequestImpersonatedToken (const TString& sessionToken, const TString& serviceAccountId, const NActors::TActorContext& ctx) {
41
70
LOG_DEBUG_S (ctx, EService::MVP, " Request impersonated token" );
42
- NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestPost (Settings.GetExchangeEndpointURL ());
71
+ NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestPost (Settings.GetImpersonateEndpointURL ());
43
72
httpRequest->Set <&NHttp::THttpRequest::ContentType>(" application/x-www-form-urlencoded" );
44
73
45
74
TMvpTokenator* tokenator = MVPAppData ()->Tokenator ;
@@ -48,16 +77,28 @@ void THandlerImpersonateStart::RequestImpersonatedToken(const TString sessionTok
48
77
token = tokenator->GetToken (Settings.SessionServiceTokenName );
49
78
}
50
79
httpRequest->Set (" Authorization" , token); // Bearer included
80
+
51
81
TStringBuilder body;
52
- body << " grant_type=urn:ietf:params:oauth:grant-type:token-exchange"
53
- << " &requested_token_type=urn:ietf:params:oauth:token-type:access_token"
54
- << " &subject_token_type=urn:ietf:params:oauth:token-type:session_token"
55
- << " &subject_token=" << sessionToken;
82
+ body << " session=" << sessionToken
83
+ << " &service_account_id=" << serviceAccountId;
56
84
httpRequest->Set <&NHttp::THttpRequest::Body>(body);
57
85
58
86
ctx.Send (HttpProxyId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest (httpRequest));
87
+ Become (&THandlerImpersonateStart::StateWork);
88
+ }
59
89
60
- Become (&THandlerSessionServiceCheckNebius::StateExchange);
90
+ void THandlerImpersonateStart::ProcessImpersonatedToken (const TString& impersonatedToken, const NActors::TActorContext& ctx) {
91
+ TString impersonatedCookieName = CreateNameImpersonatedCookie (Settings.ClientId );
92
+ TString impersonatedCookieValue = Base64Encode (impersonatedToken);
93
+ LOG_DEBUG_S (ctx, EService::MVP, " Set impersonated cookie: (" << impersonatedCookieName << " : " << NKikimr::MaskTicket (impersonatedCookieValue) << " )" );
94
+
95
+ NHttp::THeadersBuilder responseHeaders;
96
+ responseHeaders.Set (" Set-Cookie" , CreateSecureCookie (impersonatedCookieName, impersonatedCookieValue));
97
+ SetCORS (Request, &responseHeaders);
98
+ NHttp::THttpOutgoingResponsePtr httpResponse;
99
+ httpResponse = Request->CreateResponse (" 200" , " OK" , responseHeaders);
100
+ ctx.Send (Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse (httpResponse));
101
+ Die (ctx);
61
102
}
62
103
63
104
void THandlerImpersonateStart::Handle (NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr event, const NActors::TActorContext& ctx) {
@@ -70,13 +111,13 @@ void THandlerImpersonateStart::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRespon
70
111
NJson::TJsonValue jsonValue;
71
112
NJson::TJsonReaderConfig jsonConfig;
72
113
if (NJson::ReadJsonTree (response->Body , &jsonConfig, &jsonValue)) {
73
- const NJson::TJsonValue* jsonAccessToken ;
74
- if (jsonValue.GetValuePointer (" access_token " , &jsonAccessToken )) {
75
- TString sessionToken = jsonAccessToken ->GetStringRobust ();
76
- ProcessSessionToken (sessionToken , ctx);
114
+ const NJson::TJsonValue* jsonImpersonatedToken ;
115
+ if (jsonValue.GetValuePointer (" impersonation " , &jsonImpersonatedToken )) {
116
+ TString impersonatedToken = jsonImpersonatedToken ->GetStringRobust ();
117
+ ProcessImpersonatedToken (impersonatedToken , ctx);
77
118
return ;
78
119
} else {
79
- jsonError = " Wrong OIDC provider response: access_token not found" ;
120
+ jsonError = " Wrong OIDC provider response: impersonated token not found" ;
80
121
}
81
122
} else {
82
123
jsonError = " Wrong OIDC response" ;
@@ -98,51 +139,14 @@ void THandlerImpersonateStart::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRespon
98
139
Die (ctx);
99
140
}
100
141
101
- TString THandlerImpersonateStart::ChangeSameSiteFieldInSessionCookie (const TString& cookie) {
102
- const static TStringBuf SameSiteParameter {" SameSite=Lax" };
103
- size_t n = cookie.find (SameSiteParameter);
104
- if (n == TString::npos) {
105
- return cookie;
106
- }
107
- TStringBuilder cookieBuilder;
108
- cookieBuilder << cookie.substr (0 , n);
109
- cookieBuilder << " SameSite=None" ;
110
- cookieBuilder << cookie.substr (n + SameSiteParameter.size ());
111
- return cookieBuilder;
112
- }
113
-
114
- void THandlerImpersonateStart::RetryRequestToProtectedResourceAndDie (const NActors::TActorContext& ctx) {
115
- NHttp::THeadersBuilder responseHeaders;
116
- RetryRequestToProtectedResourceAndDie (&responseHeaders, ctx);
117
- }
118
-
119
- void THandlerImpersonateStart::RetryRequestToProtectedResourceAndDie (NHttp::THeadersBuilder* responseHeaders, const NActors::TActorContext& ctx) {
120
- SetCORS (Request, responseHeaders);
121
- responseHeaders->Set (" Location" , Context.GetRequestedAddress ());
122
- ctx.Send (Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse (Request->CreateResponse (" 302" , " Found" , *responseHeaders)));
123
- Die (ctx);
124
- }
142
+ TImpersonateStartPageHandler::TImpersonateStartPageHandler (const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings)
143
+ : TBase(&TImpersonateStartPageHandler::StateWork)
144
+ , HttpProxyId(httpProxyId)
145
+ , Settings(settings)
146
+ {}
125
147
126
- void THandlerImpersonateStart::SendUnknownErrorResponseAndDie (const NActors::TActorContext& ctx) {
127
- NHttp::THeadersBuilder responseHeaders;
128
- responseHeaders.Set (" Content-Type" , " text/html" );
129
- SetCORS (Request, &responseHeaders);
130
- const static TStringBuf BAD_REQUEST_HTML_PAGE = " <html>"
131
- " <head>"
132
- " <title>"
133
- " 400 Bad Request"
134
- " </title>"
135
- " </head>"
136
- " <body bgcolor=\" white\" >"
137
- " <center>"
138
- " <h1>"
139
- " Unknown error has occurred. Please open the page again"
140
- " </h1>"
141
- " </center>"
142
- " </body>"
143
- " </html>" ;
144
- ctx.Send (Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse (Request->CreateResponse (" 400" , " Bad Request" , responseHeaders, BAD_REQUEST_HTML_PAGE)));
145
- Die (ctx);
148
+ void TImpersonateStartPageHandler::Handle (NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) {
149
+ ctx.Register (new THandlerImpersonateStart (event->Sender , event->Get ()->Request , HttpProxyId, Settings));
146
150
}
147
151
148
152
} // NOIDC
0 commit comments