Skip to content

Commit d4e474b

Browse files
authored
Merge pull request #1016 from fatpeppapig/new_ui_oidc
Added support OIDC in New UI.
2 parents 90e3860 + b053947 commit d4e474b

3 files changed

Lines changed: 72 additions & 18 deletions

File tree

source/app/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def ac_current_user_has_manage_perms():
126126
]}})
127127

128128

129-
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
129+
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)
130130
#app.wsgi_app = store.wsgi_middleware(app.wsgi_app)
131131

132132
socket_io = SocketIO(app, cors_allowed_origins="*")

source/app/blueprints/pages/login/login_routes.py

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,25 @@ def oidc_login():
177177
session["oidc_state"] = rndstr()
178178
session["oidc_nonce"] = rndstr()
179179

180+
xf_proto = request.headers.get("X-Forwarded-Proto")
181+
xf_host = request.headers.get("X-Forwarded-Host")
182+
183+
if xf_proto:
184+
xf_proto = xf_proto.split(",")[0].strip()
185+
if xf_host:
186+
xf_host = xf_host.split(",")[0].strip()
187+
188+
redirect_uri = url_for("login.oidc_authorise", _external=True)
189+
190+
if xf_proto and xf_host:
191+
redirect_uri = f"{xf_proto}://{xf_host}/oidc-authorize"
192+
180193
args = {
181194
"client_id": oidc_client.client_id,
182195
"response_type": "code",
183196
"scope": app.config.get("OIDC_SCOPES"),
184197
"nonce": session["oidc_nonce"],
185-
"redirect_uri": url_for("login.oidc_authorise", _external=True),
198+
"redirect_uri": redirect_uri,
186199
"state": session["oidc_state"],
187200
}
188201

@@ -212,6 +225,18 @@ def oidc_authorise():
212225
"code": auth_resp["code"],
213226
}
214227

228+
xf_proto = request.headers.get("X-Forwarded-Proto")
229+
xf_host = request.headers.get("X-Forwarded-Host")
230+
231+
if xf_proto:
232+
xf_proto = xf_proto.split(",")[0].strip()
233+
if xf_host:
234+
xf_host = xf_host.split(",")[0].strip()
235+
236+
if xf_proto and xf_host:
237+
public_base = f"{xf_proto}://{xf_host}"
238+
args["redirect_uri"] = f"{public_base}/oidc-authorize"
239+
215240
access_token_resp = oidc_client.do_access_token_request(
216241
state=auth_resp["state"], request_args=args
217242
)
@@ -223,25 +248,32 @@ def oidc_authorise():
223248
usergroup_field = app.config.get("OIDC_MAPPING_USERGROUP")
224249
userroles_mapping_field = app.config.get("OIDC_MAPPING_ROLES")
225250
try:
226-
if "id_token" not in access_token_resp:
227-
log.error(
228-
"OIDC authentication failed: 'id_token' not found in access token response"
229-
)
230-
track_activity(
231-
"OIDC authentication failed: missing id_token in response",
232-
ctx_less=True,
233-
display_in_ui=False,
251+
if "id_token" in access_token_resp and access_token_resp["id_token"]:
252+
claims = access_token_resp["id_token"]
253+
else:
254+
if "access_token" not in access_token_resp:
255+
err = access_token_resp.get("error")
256+
desc = access_token_resp.get("error_description")
257+
log.error(
258+
f"OIDC authentication failed: token response missing access_token (error={err}, desc={desc})"
259+
)
260+
track_activity(
261+
f"OIDC authentication failed: token response missing access_token (error={err}, desc={desc})",
262+
ctx_less=True,
263+
display_in_ui=False,
264+
)
265+
return redirect(url_for("login.login"))
266+
267+
claims = oidc_client.do_user_info_request(
268+
state=auth_resp["state"],
269+
access_token=access_token_resp["access_token"],
234270
)
235-
return redirect(url_for("login.login"))
236271

237-
user_login = access_token_resp["id_token"].get(
238-
username_field
239-
) or access_token_resp["id_token"].get(email_field)
240-
user_name = access_token_resp["id_token"].get(
241-
email_field
242-
) or access_token_resp["id_token"].get(username_field)
272+
user_login = claims.get(username_field) or claims.get(email_field)
273+
user_name = claims.get(email_field) or claims.get(username_field)
274+
243275
if usergroup_field is not None:
244-
user_group = access_token_resp["id_token"].get(usergroup_field)
276+
user_group = claims.get(usergroup_field)
245277
else:
246278
user_group = None
247279

source/app/blueprints/rest/v2/auth.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,28 @@ def login():
8686
return response_api_success(data=user_data)
8787

8888

89+
@auth_blueprint.get('/whoami')
90+
def whoami():
91+
"""
92+
Returns current authenticated user info (based on the existing session) and API tokens.
93+
Output shape matches the frontend's existing local-login handler:
94+
{ responseData, tokenInfo, redirectTo }
95+
"""
96+
if not iris_current_user.is_authenticated:
97+
return response_api_error('Unauthorized', 401)
98+
99+
user = users_get_active(iris_current_user.id)
100+
response_data = UserSchema(exclude=['user_password', 'mfa_secrets', 'webauthn_credentials']).dump(user)
101+
102+
token_info = generate_auth_tokens(user)
103+
104+
return response_api_success(data={
105+
'responseData': response_data,
106+
'tokenInfo': token_info,
107+
'redirectTo': '/'
108+
})
109+
110+
89111
@auth_blueprint.post('/logout')
90112
def logout():
91113
"""

0 commit comments

Comments
 (0)