2 * Copyright © 2018 Inocybe Technologies and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.aaa.authenticator;
10 import static java.util.Objects.requireNonNull;
12 import java.nio.charset.StandardCharsets;
13 import java.util.Base64;
14 import javax.servlet.http.HttpServletRequest;
15 import org.apache.shiro.ShiroException;
16 import org.apache.shiro.authc.AuthenticationException;
17 import org.apache.shiro.authc.UsernamePasswordToken;
18 import org.apache.shiro.session.Session;
19 import org.apache.shiro.session.UnknownSessionException;
20 import org.apache.shiro.subject.Subject;
21 import org.apache.shiro.web.env.WebEnvironment;
22 import org.jolokia.osgi.security.Authenticator;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * AAA hook for <code>odl-jolokia</code> configured w/ <code>org.jolokia.authMode=service-all</code>.
29 public class ODLAuthenticator implements Authenticator {
30 private static final Logger LOG = LoggerFactory.getLogger(ODLAuthenticator.class);
32 private final WebEnvironment env;
34 public ODLAuthenticator(final WebEnvironment env) {
35 this.env = requireNonNull(env);
39 public boolean authenticate(final HttpServletRequest httpServletRequest) {
40 final String authorization = httpServletRequest.getHeader("Authorization");
42 LOG.trace("Incoming Jolokia authentication attempt: {}", authorization);
44 if (authorization == null || !authorization.startsWith("Basic")) {
49 final String base64Creds = authorization.substring("Basic".length()).trim();
50 final String credentials = new String(Base64.getDecoder().decode(base64Creds), StandardCharsets.UTF_8);
51 final String[] values = credentials.split(":", 2);
52 final UsernamePasswordToken upt = new UsernamePasswordToken();
53 upt.setUsername(values[0]);
54 upt.setPassword(values[1].toCharArray());
56 final Subject subject = new Subject.Builder(env.getSecurityManager()).buildSubject();
58 return login(subject, upt);
59 } catch (UnknownSessionException e) {
60 LOG.debug("Couldn't log in {} - logging out and retrying...", upt, e);
62 return login(subject, upt);
64 } catch (ArrayIndexOutOfBoundsException e) {
65 // FIXME: who throws this above and why do we need to catch it? Should this be error or warn?
66 LOG.trace("Formatting issue with basic auth credentials: {}", authorization, e);
72 private static void logout(final Subject subject) {
75 Session session = subject.getSession(false);
76 if (session != null) {
79 } catch (ShiroException e) {
80 LOG.debug("Couldn't log out {}", subject, e);
84 private static boolean login(final Subject subject, final UsernamePasswordToken upt) {
87 } catch (AuthenticationException e) {
88 LOG.trace("Couldn't authenticate the subject: {}", subject, e);