Example usage for javax.security.auth.message AuthException initCause

List of usage examples for javax.security.auth.message AuthException initCause

Introduction

In this page you can find the example usage for javax.security.auth.message AuthException initCause.

Prototype

public synchronized Throwable initCause(Throwable cause) 

Source Link

Document

Initializes the cause of this throwable to the specified value.

Usage

From source file:net.java.jaspicoil.SimpleBasicServerAuthModule.java

/**
 * Authenticate a received service request.
 * <p/>/*from www. j a  va  2 s  . c  o  m*/
 * This method is called to transform the mechanism-specific request message
 * acquired by calling getRequestMessage (on messageInfo) into the validated
 * application message to be returned to the message processing runtime. If
 * the received message is a (mechanism-specific) meta-message, the method
 * implementation must attempt to transform the meta-message into a
 * corresponding mechanism-specific response message, or to the validated
 * application request message. The runtime will bind a validated
 * application message into the the corresponding service invocation.
 * <p>
 * This method conveys the outcome of its message processing either by
 * returning an AuthStatus value or by throwing an AuthException.
 * <p/>
 * From a performance point of view this method will be called twice for
 * each resource with a security constraint on it. Resources with no
 * security constraint do not result in a call to this method.
 * 
 * @param messageInfo
 *            A contextual object that encapsulates the client request and
 *            server response objects, and that may be used to save state
 *            across a sequence of calls made to the methods of this
 *            interface for the purpose of completing a secure message
 *            exchange.
 * @param clientSubject
 *            A Subject that represents the source of the service request.
 *            It is used by the method implementation to store Principals
 *            and credentials validated in the request.
 * @param serviceSubject
 *            A Subject that represents the recipient of the service
 *            request, or null. It may be used by the method implementation
 *            as the source of Principals or credentials to be used to
 *            validate the request. If the Subject is not null, the method
 *            implementation may add additional Principals or credentials
 *            (pertaining to the recipient of the service request) to the
 *            Subject.
 * @return An AuthStatus object representing the completion status of the
 *         processing performed by the method. The AuthStatus values that
 *         may be returned by this method are defined as follows:
 *         <p/>
 *         <ul>
 *         <li>AuthStatus.SUCCESS when the application request message was
 *         successfully validated. The validated request message is
 *         available by calling getRequestMessage on messageInfo.
 *         <p/>
 *         <li>AuthStatus.SEND_SUCCESS to indicate that
 *         validation/processing of the request message successfully
 *         produced the secured application response message (in
 *         messageInfo). The secured response message is available by
 *         calling getResponseMessage on messageInfo.
 *         <p/>
 *         <li>AuthStatus.SEND_CONTINUE to indicate that message validation
 *         is incomplete, and that a preliminary response was returned as
 *         the response message in messageInfo.
 *         <p/>
 *         When this status value is returned to challenge an application
 *         request message, the challenged request must be saved by the
 *         authentication module such that it can be recovered when the
 *         module's validateRequest message is called to process the request
 *         returned for the challenge.
 *         <p/>
 *         <li>AuthStatus.SEND_FAILURE to indicate that message validation
 *         failed and that an appropriate failure response message is
 *         available by calling getResponseMessage on messageInfo.
 *         </ul>
 * @throws AuthException When the message processing failed without
 *         establishing a failure response message (in messageInfo).
 */
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
        throws AuthException {
    // Get the servlet context
    final HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
    final HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
    final String auth = request.getHeader(AUTHORIZATION_HEADER);
    // Test prefix for HTTP BASIC Auth
    if (auth != null && StringUtils.startsWithIgnoreCase(auth, "basic ")) {
        // We might have a valid header, so try to decode it
        final String data = new String(Base64.decodeBase64(auth.substring(BASIC_PREFIX_LENGTH)), UTF_8);
        final int splitIndex = data.indexOf(':');
        if (splitIndex < 0) {
            return sendErrorAndAuthenticateRequest(request, response, "Wrong WWW-Authenticate header format");
        }
        final String username = data.substring(splitIndex);
        final char[] password = data.substring(splitIndex + 1, data.length()).toCharArray();

        // Prepare the JAAS callback to feed any LoginModule with user and password
        final NameCallback nameCallback = new NameCallback("username");
        nameCallback.setName(username);

        final PasswordCallback passwordCallback = new PasswordCallback(getRealm(request), false);
        passwordCallback.setPassword(password);

        final CallbackHandler delegatedHandler = new CallbackHandler() {
            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
                for (int i = 0; i < callbacks.length; i++) {
                    final Callback c = callbacks[i];
                    if (c instanceof NameCallback) {
                        ((NameCallback) c).setName(username);
                    } else if (c instanceof PasswordCallback) {
                        ((PasswordCallback) c).setPassword(password);
                    } else {
                        throw new UnsupportedOperationException(
                                String.format("Callback type %s (%s) is not supported yet.", c.getClass(), c));
                    }
                }
            }
        };

        if (this.jaasContextName == null) {
            throw new UnsupportedOperationException(
                    "No delegate JAAS context found. As per JASPIC JAAS Bridge profile, this parameter is requiered.");
        }

        try {
            // Create a new JAAS context with the delegated data & try to login
            final LoginContext context = new LoginContext(this.jaasContextName, delegatedHandler);
            context.login();

            // Get the authenticated subject from the JAAS context
            Subject authenticatedSubject = context.getSubject();

            final PasswordValidationCallback passwordValidationCallback = new PasswordValidationCallback(
                    authenticatedSubject, username, password);

            // notify JASPIC containerr for the name, password and subject
            this.handler.handle(new Callback[] { passwordValidationCallback });

        } catch (final LoginException ex) {
            // If there was any issue during the JAAS login, fail the process
            final AuthException aex = new AuthException(
                    String.format("Fail to login user %s with the delegated JAAS context %s", username,
                            this.jaasContextName));
            aex.initCause(ex);
        } catch (final IOException e) {
            LOG.log(Level.WARNING, "Unable to call the handlers for name=" + nameCallback, e);
        } catch (final UnsupportedCallbackException e) {
            LOG.log(Level.WARNING, "Unable to call the handlers for name=" + nameCallback, e);
        }

    } else if (this.mandatory) {
        return sendErrorAndAuthenticateRequest(request, response,
                "AuthModule was mandatory but no valid credential was provided");
    } else {
        LOG.info("No authentication was provided bu Basic AuthModule is not mandatory so return SUCCESS.");
    }

    return AuthStatus.SUCCESS;
}

From source file:net.java.jaspicoil.MSPacSpnegoServerAuthModule.java

/**
 * Authenticate a received service request.
 * <p/>// w w  w . j  a  v  a  2  s.  c  om
 * This method is called to transform the mechanism-specific request message
 * acquired by calling getRequestMessage (on messageInfo) into the validated
 * application message to be returned to the message processing runtime. If
 * the received message is a (mechanism-specific) meta-message, the method
 * implementation must attempt to transform the meta-message into a
 * corresponding mechanism-specific response message, or to the validated
 * application request message. The runtime will bind a validated
 * application message into the the corresponding service invocation.
 * <p>
 * This method conveys the outcome of its message processing either by
 * returning an AuthStatus value or by throwing an AuthException.
 * <p/>
 * From a performance point of view this method will be called twice for
 * each resource with a security constraint on it. Resources with no
 * security constraint do not result in a call to this method.
 * 
 * @param messageInfo
 *            A contextual object that encapsulates the client request and
 *            server response objects, and that may be used to save state
 *            across a sequence of calls made to the methods of this
 *            interface for the purpose of completing a secure message
 *            exchange.
 * @param clientSubject
 *            A Subject that represents the source of the service request.
 *            It is used by the method implementation to store Principals
 *            and credentials validated in the request.
 * @param serviceSubject
 *            A Subject that represents the recipient of the service
 *            request, or null. It may be used by the method implementation
 *            as the source of Principals or credentials to be used to
 *            validate the request. If the Subject is not null, the method
 *            implementation may add additional Principals or credentials
 *            (pertaining to the recipient of the service request) to the
 *            Subject.
 * @return An AuthStatus object representing the completion status of the
 *         processing performed by the method. The AuthStatus values that
 *         may be returned by this method are defined as follows:
 *         <p/>
 *         <ul>
 *         <li>AuthStatus.SUCCESS when the application request message was
 *         successfully validated. The validated request message is
 *         available by calling getRequestMessage on messageInfo.
 *         <p/>
 *         <li>AuthStatus.SEND_SUCCESS to indicate that
 *         validation/processing of the request message successfully
 *         produced the secured application response message (in
 *         messageInfo). The secured response message is available by
 *         calling getResponseMessage on messageInfo.
 *         <p/>
 *         <li>AuthStatus.SEND_CONTINUE to indicate that message validation
 *         is incomplete, and that a preliminary response was returned as
 *         the response message in messageInfo.
 *         <p/>
 *         When this status value is returned to challenge an application
 *         request message, the challenged request must be saved by the
 *         authentication module such that it can be recovered when the
 *         module's validateRequest message is called to process the request
 *         returned for the challenge.
 *         <p/>
 *         <li>AuthStatus.SEND_FAILURE to indicate that message validation
 *         failed and that an appropriate failure response message is
 *         available by calling getResponseMessage on messageInfo.
 *         </ul>
 * @throws AuthException When the message processing failed without
 *         establishing a failure response message (in messageInfo).
 */
@SuppressWarnings("unchecked")
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
        throws AuthException {

    // Extra check (disabled withour -ea) if mandatory value is consistent
    // with initialize phase
    assert messageInfo.getMap().containsKey(IS_MANDATORY_INFO_KEY) == this.mandatory;

    // Get the servlet context
    final HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
    final HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();

    // Invalidate any existing session to prevent session fixture attempt
    HttpSession session = request.getSession(false);
    if (session != null) {
        final SessionState state = (SessionState) session.getAttribute(MAGIC_SESSION_STATE_KEY);
        if (state == null) {
            // Session was not created by us, we will invalidate an existing
            // session that was not created by us
            session.invalidate();
            LOG.warning(
                    "An existing session was invalidated. This might be a session fixture attempt, so failing the authentication.");
            return AuthStatus.SEND_FAILURE;
        } else if (SessionState.ESTABLISHED.equals(state)) {
            // The context was already fully established once within this
            // session.
            return AuthStatus.SUCCESS;
        }
    }

    debugRequest(request);

    // should specify encoder
    final String authorization = request.getHeader(AUTHORIZATION_HEADER);

    if (authorization != null && authorization.startsWith(NEGOTIATE)) {

        final String negotiateString = authorization.substring(NEGOTIATE.length() + 1);

        final byte[] requestToken = Base64.decodeBase64(negotiateString);

        if (serviceSubject == null) {
            // If no service subject was provided by the container then set
            // a service subject
            // from the global context.
            serviceSubject = this.serviceSubject;
        }

        try {
            // Create a validation action
            byte[] gssToken = null;
            final KerberosValidateAction kva = new KerberosValidateAction(this.servicePrincipal, requestToken,
                    serviceSubject);
            try {
                // Validate using the service (server) Subject
                gssToken = Subject.doAs(this.serviceSubject, kva);
            } catch (final PrivilegedActionException e) {
                final GSSException gex = new GSSException(GSSException.DEFECTIVE_TOKEN);
                gex.initCause(e);
                gex.setMinor(GSSException.UNAVAILABLE, "Unable to perform Kerberos validation");
                throw gex;
            }

            if (kva.getContext() != null) {
                final String responseToken = Base64.encodeBase64String(gssToken);
                response.setHeader(AUTHENTICATION_HEADER, "Negotiate " + responseToken);
                debugToken("GSS Response token set to {0}", gssToken);
            }

            if (!kva.isEstablished()) {
                debug("GSS Dialog must continue to succeed");

                session.setAttribute(MAGIC_SESSION_STATE_KEY, SessionState.IN_PROGRESS);

                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                return AuthStatus.SEND_CONTINUE;

            } else {

                final Oid mechId = kva.getMech();
                final GSSName name = kva.getSrcName();

                if (!authorizeCaller(request, requestToken, name, clientSubject)) {
                    return sendFailureMessage(response, "Failed to authorize the caller/client");
                }

                // As no valid session should exist anymore, simply create a
                // new one
                session = request.getSession(true);

                final Principal clientPrincipal = new KerberosPrincipal(
                        name.canonicalize(GSS_KRB5_MECH_OID).toString());

                updateSessionAndHeader(request, session, clientPrincipal);

                session.setAttribute(MAGIC_SESSION_STATE_KEY, SessionState.ESTABLISHED);
                /*
                 * Store the mechId in the MessageInfo to indicate which
                 * authentication mechanism was used successfully (JASPIC
                 * Requirement)
                 */
                messageInfo.getMap().put(AUTH_TYPE_INFO_KEY,
                        mechId != null ? mechId.toString() : "Undefined GSS Mechanism");

                debug("GSS Dialog is complete");

            }

        } catch (final GSSException gsse) {
            debug("GSS Dialog has failed : {0}", gsse);

            if (requestToken != null) {
                debug("Bad token detected {0}", gsse);
                debugToken("Bad token was {0}", requestToken);

                if (isNTLMToken(requestToken)) {
                    // There is a high probability it was a NTLM SPNEGO
                    // token
                    return sendFailureMessage(response, "No support for NTLM");
                }
            }

            // for other errors throw an AuthException
            final AuthException ae = new AuthException();
            ae.initCause(gsse);
            throw ae;
        }

    } else if (this.mandatory) {

        response.setHeader(AUTHENTICATION_HEADER, NEGOTIATE);
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        debug("Negotiate was added to the HTTP header : {0}", NEGOTIATE);

        return AuthStatus.SEND_CONTINUE;

    } else if (authorization != null) {
        LOG.warning("An authorization header was ignored.");
    }

    return AuthStatus.SUCCESS;
}

From source file:net.java.jaspicoil.MSPacSpnegoServerAuthModule.java

/**
 * Initialize this module with request and response message policies to
 * enforce, a CallbackHandler, and any module-specific configuration
 * properties. The request policy and the response policy must not both be
 * null.//from ww w.  ja  va2s  . c  o  m
 * 
 * @param requestPolicy
 *            The request policy this module must enforce, or null.
 * @param responsePolicy
 *            The response policy this module must enforce, or null.
 * @param handler
 *            CallbackHandler used to request information.
 * @param options
 *            A Map of module-specific configuration properties.
 * @throws AuthException
 *             If module initialization fails, including for the case where
 *             the options argument contains elements that are not supported
 *             by the module.
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
        Map options) throws AuthException {

    boolean useDelegatedLoginModule = false;
    // If no options or empty options was provided get away and display some
    // usage log
    // Please note that some AS such as JBoss 7 call this method twice.
    if (options == null || options.isEmpty()) {
        LOG.warning(String.format(
                "Options is either empty or null this time. Please make sure that "
                        + "at least the parameter %s and %s are set in the JASPIC provider configuration.",
                SERVICE_PRINCIPAL_NAME_KEY, KEYTAB_LOCATION_KEY));
        return;
    }

    this.requestPolicy = requestPolicy;
    this.responsePolicy = responsePolicy;

    // If none policy was provided, we assume this provider is mandatory.
    // This is unfortunately required as some container issue workaround
    this.mandatory = requestPolicy != null ? requestPolicy.isMandatory() : true;

    this.handler = handler;
    this.options = options;

    this.debug = options.containsKey(DEBUG_OPTIONS_KEY);

    // Set the debug level according to the logger config and the JASPIC
    // config
    this.debugLevel = LOG.isLoggable(Level.FINE) && !this.debug ? Level.FINE : Level.INFO;
    debug("Debug was set ({0},{1})", this.debug, this.debugLevel);

    this.jaasContextName = (String) options.get(JAAS_CONTEXT_KEY);
    debug("Jaas context name was set {0}", this.jaasContextName);

    if (this.jaasContextName == null && this.loginModuleName != null) {
        debug("There was no JAAS context parameter set on the JASPIC so using the default passed from the application server");
        this.jaasContextName = this.loginModuleName;
        useDelegatedLoginModule = true;
    }

    this.policyContextID = (String) options.get(POLICY_CONTEXT_OPTIONS_KEY);
    debug("Policy context set to {0}", this.policyContextID);

    this.servicePrincipal = (String) options.get(SERVICE_PRINCIPAL_NAME_KEY);
    debug("Principal set to {0}", this.servicePrincipal);

    // If there was no delegated LoginModule found we must set a SPN
    if (!useDelegatedLoginModule && this.servicePrincipal == null) {
        LOG.severe("A valid SPN must be configured for JASPIC connector with the property "
                + SERVICE_PRINCIPAL_NAME_KEY);
        return;
    }

    // Get the secure groups
    final String groupList = (String) options.get(SECURE_GROUP_SIDS_KEY);
    if (groupList != null && !"".equals(groupList.trim())) {
        this.secureGroups = Collections
                .unmodifiableSet(new HashSet<String>(Arrays.asList(groupList.trim().split(","))));
        debug("Secure groups set as: {0}", this.secureGroups);
    }

    // Get the mandatory groups
    final String mandatoryGroupList = (String) options.get(MANDATORY_GROUPS_KEY);
    if (mandatoryGroupList != null && !"".equals(mandatoryGroupList.trim())) {
        this.mandatoryGroups = Collections
                .unmodifiableSet(new HashSet<String>(Arrays.asList(mandatoryGroupList.trim().split(","))));
        debug("Mandatory groups set as: {0}", this.mandatoryGroups);
    }

    final String administratorGroupList = (String) options.get(ADMINISTRATOR_GROUPS_KEY);
    if (administratorGroupList != null && !"".equals(administratorGroupList.trim())) {
        this.administratorGroups = Collections
                .unmodifiableSet(new HashSet<String>(Arrays.asList(administratorGroupList.trim().split(","))));
        debug("Administrator groups set as: {0}", this.mandatoryGroups);
    }

    final String administratorOnlyUriList = (String) options.get(ADMINISTRATOR_ONLY_URIS_KEY);
    if (administratorOnlyUriList != null && !"".equals(administratorOnlyUriList.trim())) {
        this.administratorOnlyUris = Collections.unmodifiableSet(
                new HashSet<String>(Arrays.asList(administratorOnlyUriList.trim().split(","))));
        debug("Administrator restricted URIs set as: {0}", this.mandatoryGroups);
    }

    final String sessionAttributeList = (String) options.get(SESSION_ATTRIBUTES_KEY);
    if (sessionAttributeList != null && !"".equals(sessionAttributeList.trim())) {
        final String[] pairs = sessionAttributeList.trim().split(",");
        final Map<String, String> attributes = new HashMap<String, String>();
        for (final String pair : pairs) {
            final String[] vals = pair.split("=");
            attributes.put(vals[0], vals[1]);
        }
        this.sessionAttributes = Collections.unmodifiableMap(attributes);
        debug("Session attributes was set to {0}", this.sessionAttributes);
    }

    final String keyTabLocationString = (String) options.get(KEYTAB_LOCATION_KEY);
    if (!useDelegatedLoginModule && keyTabLocationString == null) {
        LOG.severe("A valid key tab location must be configured for JASPIC connector with the property "
                + KEYTAB_LOCATION_KEY);
        return;
    }

    if (keyTabLocationString != null) {
        // Try to reference the indicated keytab
        try {
            this.keyTabLocation = new URL(keyTabLocationString);
            debug("Keytab location was set to {0}", this.keyTabLocation);
        } catch (final MalformedURLException e) {
            LOG.log(Level.WARNING, "Unable to build " + KEYTAB_LOCATION_KEY + " from the parameter value "
                    + options.get(KEYTAB_LOCATION_KEY), e);
        }
    }

    URL groupMappingSource = null;
    try {
        final String groupParam = (String) options.get(GROUP_MAPPING_KEY);
        if (groupParam != null && !"".equals(groupParam.trim())) {
            groupMappingSource = new URL(groupParam);
        }

    } catch (final MalformedURLException e) {
        LOG.log(Level.WARNING, "Unable to build " + GROUP_MAPPING_KEY + " from the parameter value "
                + options.get(GROUP_MAPPING_KEY), e);
    }
    if (groupMappingSource != null) {
        final Properties groupMapping = new Properties();

        try {
            InputStream groupMappingInputstream = null;
            try {
                groupMappingInputstream = groupMappingSource.openStream();
                groupMapping.load(groupMappingInputstream);
            } finally {
                if (groupMappingInputstream != null) {
                    groupMappingInputstream.close();
                }
            }
            this.groupMapping = groupMapping;
            debug("Group mapping was set to {0}", this.groupMapping);
        } catch (final IOException ioex) {
            LOG.log(Level.WARNING, "Unable to load " + GROUP_MAPPING_KEY + " from the indicated ressource "
                    + options.get(GROUP_MAPPING_KEY), ioex);
        }
    }

    try {
        // Load the serviceSubject from a LoginModule, this is required to
        // get the Kerberos Key
        this.serviceSubject = initializeKerberosServerContext(this.jaasContextName, this.servicePrincipal,
                this.keyTabLocation, this.debug);
        debug("Service subject was set to {0}", this.serviceSubject);
    } catch (final LoginException e) {
        final AuthException aex = new AuthException("Kerberos service context initialization failed");
        aex.initCause(e);
        throw aex;
    }

    this.smartcardSecuredUsersOnly = Boolean.parseBoolean((String) options.get(SMARTCARD_SECURED_USERS_ONLY));
    debug("Only accept smartcard secured users ? {0}", this.smartcardSecuredUsersOnly);

    this.delegatedSecuredUsersOnly = Boolean.parseBoolean((String) options.get(DELEGATED_SECURED_USERS_ONLY));
    debug("Only accept delegated (KCD) users ? {0}", this.delegatedSecuredUsersOnly);

    this.userHeader = (String) options.get(USER_HEADER_KEY);
    debug("User header set to {0}", this.userHeader);

    // TODO Add some fetchExtraGroupsScript handling that will use
    // javax.script to execute
    // an idea is to use the first line as //#!!mime/type the mimetype will
    // be extracted out to known which engine to call
}