List of usage examples for javax.security.auth.message AuthException initCause
public synchronized Throwable initCause(Throwable cause)
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 }