diff --git a/plugins/src/opengrok/auth/plugin/decoders/UserPrincipalDecoder.java b/plugins/src/opengrok/auth/plugin/decoders/UserPrincipalDecoder.java new file mode 100644 index 00000000000..d349bb79055 --- /dev/null +++ b/plugins/src/opengrok/auth/plugin/decoders/UserPrincipalDecoder.java @@ -0,0 +1,58 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * See LICENSE.txt included in this distribution for the specific + * language governing permissions and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at LICENSE.txt. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + */ + +package opengrok.auth.plugin.decoders; + +import opengrok.auth.plugin.entity.User; + +import javax.servlet.http.HttpServletRequest; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Get authenticated user principal and use it to create User object. + * This works e.g. with HTTP Basic authentication headers as per RFC 7617. + * + * @author Vladimir Kotal + */ +public class UserPrincipalDecoder implements IUserDecoder { + + private static final Logger LOGGER = Logger.getLogger(UserPrincipalDecoder.class.getName()); + + @Override + public User fromRequest(HttpServletRequest request) { + if (request.getUserPrincipal() == null) { + return null; + } + + String username = request.getUserPrincipal().getName(); + if (username == null || username.isEmpty()) { + LOGGER.log(Level.WARNING, + "Can not construct User object: cannot get user principal from: {0}", + request); + return null; + } + + return new User(username); + } +} \ No newline at end of file diff --git a/plugins/test/opengrok/auth/plugin/decoders/UserPrincipalDecoderTest.java b/plugins/test/opengrok/auth/plugin/decoders/UserPrincipalDecoderTest.java new file mode 100644 index 00000000000..889102658a3 --- /dev/null +++ b/plugins/test/opengrok/auth/plugin/decoders/UserPrincipalDecoderTest.java @@ -0,0 +1,60 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * See LICENSE.txt included in this distribution for the specific + * language governing permissions and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at LICENSE.txt. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + */ + +package opengrok.auth.plugin.decoders; + +import opengrok.auth.plugin.entity.User; +import opengrok.auth.plugin.util.DummyHttpServletRequestUser; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertNull; + +public class UserPrincipalDecoderTest { + DummyHttpServletRequestUser dummyRequest; + UserPrincipalDecoder decoder = new UserPrincipalDecoder(); + + @Before + public void setUp() { + dummyRequest = new DummyHttpServletRequestUser(); + } + + @Test + public void testHttpBasicDecoding() { + dummyRequest.setHeader("authorization", "Basic Zm9vOmJhcg=="); + + User result = decoder.fromRequest(dummyRequest); + + Assert.assertNotNull(result); + Assert.assertEquals("foo", result.getUsername()); + assertNull(result.getId()); + Assert.assertFalse(result.isTimeouted()); + } + + @Test + public void testMissingHeader() { + assertNull(decoder.fromRequest(new DummyHttpServletRequestUser())); + } +} + diff --git a/plugins/test/opengrok/auth/plugin/util/DummyHttpServletRequestUser.java b/plugins/test/opengrok/auth/plugin/util/DummyHttpServletRequestUser.java index 5685337ff7b..27b4e97c2fc 100644 --- a/plugins/test/opengrok/auth/plugin/util/DummyHttpServletRequestUser.java +++ b/plugins/test/opengrok/auth/plugin/util/DummyHttpServletRequestUser.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.Principal; +import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; @@ -217,7 +218,24 @@ public boolean isUserInRole(String string) { @Override public Principal getUserPrincipal() { - throw new UnsupportedOperationException("Not supported yet."); + String authHeader = getHeader("authorization"); + if (authHeader == null) { + return null; + } + + if (!authHeader.startsWith("Basic")) { + return null; + } + + String encodedValue = authHeader.split(" ")[1]; + Base64.Decoder decoder = Base64.getDecoder(); + String username = new String(decoder.decode(encodedValue)).split(":")[0]; + return new Principal() { + @Override + public String getName() { + return username; + } + }; } @Override