1
1
#include < library/cpp/json/json_reader.h>
2
2
#include < library/cpp/string_utils/base64/base64.h>
3
3
#include < ydb/library/actors/http/http.h>
4
+ #include < ydb/library/security/util.h>
4
5
#include < ydb/mvp/core/mvp_log.h>
6
+ #include < ydb/mvp/core/mvp_tokens.h>
5
7
#include " openid_connect.h"
6
8
#include " oidc_session_create.h"
7
9
#include " oidc_settings.h"
10
+ #include " oidc_impersonate_start_page_nebius.h"
8
11
9
12
namespace NMVP {
10
13
namespace NOIDC {
11
14
12
15
THandlerImpersonateStart::THandlerImpersonateStart (const NActors::TActorId& sender,
13
- const NHttp::THttpIncomingRequestPtr& request,
14
- const NActors::TActorId& httpProxyId,
15
- const TOpenIdConnectSettings& settings)
16
+ const NHttp::THttpIncomingRequestPtr& request,
17
+ const NActors::TActorId& httpProxyId,
18
+ const TOpenIdConnectSettings& settings)
16
19
: Sender(sender)
17
20
, Request(request)
18
21
, HttpProxyId(httpProxyId)
19
22
, Settings(settings)
20
23
{}
21
24
25
+ TString THandlerImpersonateStart::DecodeToken (const TStringBuf& cookie, const NActors::TActorContext& ctx) {
26
+ TString token;
27
+ try {
28
+ Base64StrictDecode (cookie, token);
29
+ } catch (std::exception& e) {
30
+ LOG_DEBUG_S (ctx, EService::MVP, " Base64Decode " << cookie << " cookie: " << e.what ());
31
+ token.clear ();
32
+ }
33
+ return token;
34
+ }
35
+
22
36
void THandlerImpersonateStart::Bootstrap (const NActors::TActorContext& ctx) {
23
37
NHttp::TUrlParameters urlParameters (Request->URL );
24
38
TString serviceAccountId = urlParameters[" service_accound_id" ];
25
39
26
40
NHttp::THeaders headers (Request->Headers );
27
41
LOG_DEBUG_S (ctx, EService::MVP, " Start impersonation process" );
28
42
NHttp::TCookies cookies (headers.Get (" Cookie" ));
29
- TString sessionToken = DecodeToken (cookies, CreateNameSessionCookie (Settings.ClientId ));
30
43
31
- if (sessionToken && serviceAccountId) {
32
- RequestImpersonatedToken (sessionToken, serviceAccountId, ctx);
33
- } else {
44
+ TString sessionCookieName = CreateNameSessionCookie (Settings.ClientId );
45
+ TStringBuf sessionCookieValue = cookies.Get (sessionCookieName);
46
+ if (!sessionCookieValue.Empty ()) {
47
+ LOG_DEBUG_S (ctx, EService::MVP, " Using session cookie (" << sessionCookieName << " : " << NKikimr::MaskTicket (sessionCookieValue) << " )" );
48
+ }
49
+
50
+ TString sessionToken = DecodeToken (sessionCookieValue, ctx);
51
+
52
+ TStringBuf jsonError;
53
+ if (sessionToken.empty ()) {
54
+ jsonError = " Wrong impersonate parameter: session cookie not found" ;
55
+ } else if (serviceAccountId.empty ()) {
56
+ jsonError = " Wrong impersonate parameter: account_id not found" ;
57
+ }
58
+
59
+ if (jsonError) {
34
60
NHttp::THeadersBuilder responseHeaders;
35
61
responseHeaders.Set (" Content-Type" , " text/plain" );
36
- httpResponse = Request->CreateResponse (" 400" , " Bad Request" , responseHeaders, event->Get ()->Error );
62
+ NHttp::THttpOutgoingResponsePtr httpResponse = Request->CreateResponse (" 400" , " Bad Request" , responseHeaders, " Wrong impersonate parameter: access_token not found" );
63
+ ctx.Send (Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse (httpResponse));
64
+ Die (ctx);
65
+ } else {
66
+ RequestImpersonatedToken (sessionToken, serviceAccountId, ctx);
37
67
}
38
68
}
39
69
40
- void THandlerImpersonateStart::RequestImpersonatedToken (const TString sessionToken, const TString serviceAccountId, const NActors::TActorContext& ctx) {
41
- LOG_DEBUG_S (ctx, EService::MVP, " Request impersonated token" );
42
- NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestPost (Settings.GetExchangeEndpointURL ());
43
- httpRequest->Set <&NHttp::THttpRequest::ContentType>(" application/x-www-form-urlencoded" );
70
+ void THandlerImpersonateStart::RequestImpersonatedToken (const TString& sessionToken, const TString& serviceAccountId, const NActors::TActorContext& ctx) {
71
+ // TMvpTokenator* tokenator = MVPAppData()->Tokenator;
72
+ // TString token = "";
73
+ // if (tokenator) {
74
+ // token = tokenator->GetToken(Settings.SessionServiceTokenName);
75
+ // }
76
+ // httpRequest->Set("Authorization", token); // Bearer included
44
77
45
- TMvpTokenator* tokenator = MVPAppData ()->Tokenator ;
46
- TString token = " " ;
47
- if (tokenator) {
48
- token = tokenator->GetToken (Settings.SessionServiceTokenName );
49
- }
50
- httpRequest->Set (" Authorization" , token); // Bearer included
78
+ LOG_DEBUG_S (ctx, EService::MVP, " Request impersonated token" );
51
79
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;
80
+ body << " session=" << sessionToken
81
+ << " &service_account_id=" << serviceAccountId;
82
+
83
+ NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestPost (Settings.GetImpersonateEndpointURL ());
84
+ httpRequest->Set <&NHttp::THttpRequest::ContentType>(" application/x-www-form-urlencoded" );
85
+ httpRequest->Set (" Authorization" , Settings.GetAuthorizationString ());
56
86
httpRequest->Set <&NHttp::THttpRequest::Body>(body);
57
87
58
88
ctx.Send (HttpProxyId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest (httpRequest));
89
+ Become (&THandlerImpersonateStart::StateWork);
90
+ }
59
91
60
- Become (&THandlerSessionServiceCheckNebius::StateExchange);
92
+ void THandlerImpersonateStart::ProcessImpersonatedToken (const TString& impersonatedToken, const NActors::TActorContext& ctx) {
93
+ TString impersonatedCookieName = CreateNameImpersonatedCookie (Settings.ClientId );
94
+ TString impersonatedCookieValue = Base64Encode (impersonatedToken);
95
+ LOG_DEBUG_S (ctx, EService::MVP, " Set impersonated cookie: (" << impersonatedCookieName << " : " << NKikimr::MaskTicket (impersonatedCookieValue) << " )" );
96
+
97
+ NHttp::THeadersBuilder responseHeaders;
98
+ responseHeaders.Set (" Set-Cookie" , CreateSecureCookie (impersonatedCookieName, impersonatedCookieValue));
99
+ responseHeaders.Set (" Location" , Context.GetRequestedAddress ());
100
+ NHttp::THttpOutgoingResponsePtr httpResponse;
101
+ httpResponse = Request->CreateResponse (" 302" , " Cookie set" , responseHeaders);
102
+ ctx.Send (Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse (httpResponse));
103
+ Die (ctx);
61
104
}
62
105
63
106
void THandlerImpersonateStart::Handle (NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr event, const NActors::TActorContext& ctx) {
@@ -70,13 +113,13 @@ void THandlerImpersonateStart::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRespon
70
113
NJson::TJsonValue jsonValue;
71
114
NJson::TJsonReaderConfig jsonConfig;
72
115
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);
116
+ const NJson::TJsonValue* jsonImpersonatedToken ;
117
+ if (jsonValue.GetValuePointer (" impersonation " , &jsonImpersonatedToken )) {
118
+ TString impersonatedToken = jsonImpersonatedToken ->GetStringRobust ();
119
+ ProcessImpersonatedToken (impersonatedToken , ctx);
77
120
return ;
78
121
} else {
79
- jsonError = " Wrong OIDC provider response: access_token not found" ;
122
+ jsonError = " Wrong OIDC provider response: impersonated token not found" ;
80
123
}
81
124
} else {
82
125
jsonError = " Wrong OIDC response" ;
@@ -98,51 +141,16 @@ void THandlerImpersonateStart::Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRespon
98
141
Die (ctx);
99
142
}
100
143
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
- }
144
+ TImpersonateStartPageHandler::TImpersonateStartPageHandler (const NActors::TActorId& httpProxyId, const TOpenIdConnectSettings& settings)
145
+ : TBase(&TImpersonateStartPageHandler::StateWork)
146
+ , HttpProxyId(httpProxyId)
147
+ , Settings(settings)
148
+ {}
125
149
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);
150
+ void TImpersonateStartPageHandler::Handle (NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) {
151
+ if (Settings.AccessServiceType == NMvp::nebius_v1) {
152
+ ctx.Register (new THandlerImpersonateStart (event->Sender , event->Get ()->Request , HttpProxyId, Settings));
153
+ }
146
154
}
147
155
148
156
} // NOIDC
0 commit comments