Skip to content

Commit 3d08000

Browse files
authored
Avoid showing the sign-up prompt during the login flow. (#1145)
Motivation: In the login flow, if the session set in `/api/v0/users/me` is not valid, `WWW-Authenticate` header is included in the response headers. The header could cause a brower prompt a sign-up form. Motification: - Fix `CentralDogmaAuthFailureHandler` not to include `WWW_AUTHENTICATE` for `/api/v0/users/me` Result: The login flow is not interrupted by a basic authentication prompt. Note: Since a new release hasn’t been made yet, it doesn’t affect users.
1 parent 37cfb37 commit 3d08000

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

server/src/main/java/com/linecorp/centraldogma/server/CentralDogmaAuthFailureHandler.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ public HttpResponse authFailed(HttpService delegate,
5656
return HttpApiUtil.newResponse(ctx, HttpStatus.INTERNAL_SERVER_ERROR, cause);
5757
}
5858

59-
return HttpApiUtil.newResponse(ctx, UNAUTHORIZED_HEADERS, AUTHORIZATION_EXCEPTION);
59+
if ("/api/v0/users/me".equals(ctx.path())) {
60+
// Do not return the WWW-Authenticate header for the /api/v0/users/me to avoid triggering a sign-in
61+
// prompt in browsers. It could interfere with the login flow.
62+
return HttpApiUtil.newResponse(ctx, HttpStatus.UNAUTHORIZED, AUTHORIZATION_EXCEPTION);
63+
} else {
64+
return HttpApiUtil.newResponse(ctx, UNAUTHORIZED_HEADERS, AUTHORIZATION_EXCEPTION);
65+
}
6066
}
6167
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2025 LINE Corporation
3+
*
4+
* LINE Corporation licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package com.linecorp.centraldogma.server.internal.admin.service;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.extension.RegisterExtension;
23+
24+
import com.linecorp.armeria.client.BlockingWebClient;
25+
import com.linecorp.armeria.common.AggregatedHttpResponse;
26+
import com.linecorp.armeria.common.HttpHeaderNames;
27+
import com.linecorp.armeria.common.HttpStatus;
28+
import com.linecorp.centraldogma.server.CentralDogmaBuilder;
29+
import com.linecorp.centraldogma.server.metadata.User;
30+
import com.linecorp.centraldogma.testing.internal.auth.TestAuthMessageUtil;
31+
import com.linecorp.centraldogma.testing.internal.auth.TestAuthProviderFactory;
32+
import com.linecorp.centraldogma.testing.junit.CentralDogmaExtension;
33+
34+
class UserServiceTest {
35+
36+
@RegisterExtension
37+
static final CentralDogmaExtension dogma = new CentralDogmaExtension() {
38+
@Override
39+
protected void configure(CentralDogmaBuilder builder) {
40+
builder.authProviderFactory(new TestAuthProviderFactory());
41+
builder.systemAdministrators(TestAuthMessageUtil.USERNAME);
42+
builder.webAppEnabled(true);
43+
}
44+
};
45+
46+
@Test
47+
void shouldNotReturnWwwAuthenticateHeaderOnUnauthorized() {
48+
final BlockingWebClient client = BlockingWebClient.of(dogma.httpClient().uri());
49+
final AggregatedHttpResponse response = client.get("/api/v0/users/me");
50+
assertThat(response.status()).isEqualTo(HttpStatus.UNAUTHORIZED);
51+
assertThat(response.headers().get(HttpHeaderNames.WWW_AUTHENTICATE)).isNull();
52+
53+
final String accessToken =
54+
TestAuthMessageUtil.getAccessToken(dogma.httpClient(),
55+
TestAuthMessageUtil.USERNAME,
56+
TestAuthMessageUtil.PASSWORD);
57+
final User user = client.prepare()
58+
.get("/api/v0/users/me")
59+
.header(HttpHeaderNames.AUTHORIZATION,
60+
"Bearer " + accessToken)
61+
.asJson(User.class)
62+
.execute()
63+
.content();
64+
assertThat(user.login()).isEqualTo(TestAuthMessageUtil.USERNAME);
65+
}
66+
}

0 commit comments

Comments
 (0)