Skip to content

Commit a63edcb

Browse files
author
Vladimir Kotal
authored
add decoder for HTTP Basic auth (#2875)
aids #2872
1 parent 8ef7bc0 commit a63edcb

File tree

3 files changed

+137
-1
lines changed

3 files changed

+137
-1
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
22+
*/
23+
24+
package opengrok.auth.plugin.decoders;
25+
26+
import opengrok.auth.plugin.entity.User;
27+
28+
import javax.servlet.http.HttpServletRequest;
29+
import java.util.logging.Level;
30+
import java.util.logging.Logger;
31+
32+
/**
33+
* Get authenticated user principal and use it to create User object.
34+
* This works e.g. with HTTP Basic authentication headers as per RFC 7617.
35+
*
36+
* @author Vladimir Kotal
37+
*/
38+
public class UserPrincipalDecoder implements IUserDecoder {
39+
40+
private static final Logger LOGGER = Logger.getLogger(UserPrincipalDecoder.class.getName());
41+
42+
@Override
43+
public User fromRequest(HttpServletRequest request) {
44+
if (request.getUserPrincipal() == null) {
45+
return null;
46+
}
47+
48+
String username = request.getUserPrincipal().getName();
49+
if (username == null || username.isEmpty()) {
50+
LOGGER.log(Level.WARNING,
51+
"Can not construct User object: cannot get user principal from: {0}",
52+
request);
53+
return null;
54+
}
55+
56+
return new User(username);
57+
}
58+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
22+
*/
23+
24+
package opengrok.auth.plugin.decoders;
25+
26+
import opengrok.auth.plugin.entity.User;
27+
import opengrok.auth.plugin.util.DummyHttpServletRequestUser;
28+
import org.junit.Assert;
29+
import org.junit.Before;
30+
import org.junit.Test;
31+
32+
import static org.junit.Assert.assertNull;
33+
34+
public class UserPrincipalDecoderTest {
35+
DummyHttpServletRequestUser dummyRequest;
36+
UserPrincipalDecoder decoder = new UserPrincipalDecoder();
37+
38+
@Before
39+
public void setUp() {
40+
dummyRequest = new DummyHttpServletRequestUser();
41+
}
42+
43+
@Test
44+
public void testHttpBasicDecoding() {
45+
dummyRequest.setHeader("authorization", "Basic Zm9vOmJhcg==");
46+
47+
User result = decoder.fromRequest(dummyRequest);
48+
49+
Assert.assertNotNull(result);
50+
Assert.assertEquals("foo", result.getUsername());
51+
assertNull(result.getId());
52+
Assert.assertFalse(result.isTimeouted());
53+
}
54+
55+
@Test
56+
public void testMissingHeader() {
57+
assertNull(decoder.fromRequest(new DummyHttpServletRequestUser()));
58+
}
59+
}
60+

plugins/test/opengrok/auth/plugin/util/DummyHttpServletRequestUser.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.io.IOException;
2727
import java.io.UnsupportedEncodingException;
2828
import java.security.Principal;
29+
import java.util.Base64;
2930
import java.util.Collection;
3031
import java.util.Collections;
3132
import java.util.Enumeration;
@@ -217,7 +218,24 @@ public boolean isUserInRole(String string) {
217218

218219
@Override
219220
public Principal getUserPrincipal() {
220-
throw new UnsupportedOperationException("Not supported yet.");
221+
String authHeader = getHeader("authorization");
222+
if (authHeader == null) {
223+
return null;
224+
}
225+
226+
if (!authHeader.startsWith("Basic")) {
227+
return null;
228+
}
229+
230+
String encodedValue = authHeader.split(" ")[1];
231+
Base64.Decoder decoder = Base64.getDecoder();
232+
String username = new String(decoder.decode(encodedValue)).split(":")[0];
233+
return new Principal() {
234+
@Override
235+
public String getName() {
236+
return username;
237+
}
238+
};
221239
}
222240

223241
@Override

0 commit comments

Comments
 (0)