001/*
002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Nuxeo - initial API and implementation
018 *
019 * $Id$
020 */
021
022package org.nuxeo.runtime.api.login;
023
024import javax.security.auth.callback.Callback;
025import javax.security.auth.callback.CallbackHandler;
026import javax.security.auth.callback.NameCallback;
027import javax.security.auth.callback.PasswordCallback;
028import javax.security.auth.callback.UnsupportedCallbackException;
029
030/**
031 * The default callback handler used by Framework.login methods.
032 * <p>
033 * This callback handler supports 3 types of callbacks:
034 * <ul>
035 * <li>the standard name callback
036 * <li>the standard password callback
037 * <li>a custom credentials callback that can be used to pass specific login information.
038 * </ul>
039 *
040 * @author eionica@nuxeo.com
041 */
042public class CredentialsCallbackHandler implements CallbackHandler {
043
044    private final String name;
045
046    private final Object credentials;
047
048    public CredentialsCallbackHandler(String username, Object credentials) {
049        this.name = username;
050        this.credentials = credentials;
051    }
052
053    @Override
054    public void handle(Callback[] callbacks) throws UnsupportedCallbackException {
055        for (Callback cb : callbacks) {
056            if (cb instanceof NameCallback) {
057                ((NameCallback) cb).setName(name);
058            } else if (cb instanceof PasswordCallback) {
059                if (credentials instanceof CharSequence) {
060                    // TODO cache the password to avoid recomputing it?
061                    ((PasswordCallback) cb).setPassword(credentials.toString().toCharArray());
062                } else if (credentials instanceof char[]) {
063                    ((PasswordCallback) cb).setPassword((char[]) credentials);
064                } else {
065                    // the credentials are not in a password format. use null
066                    ((PasswordCallback) cb).setPassword(null);
067                }
068            } else if (cb instanceof CredentialsCallback) {
069                // if neither name or password callback are given use the generic credentials callback
070                ((CredentialsCallback) cb).setCredentials(credentials);
071            } else {
072                throw new UnsupportedCallbackException(cb, "Unsupported callback " + cb + ". "
073                        + "Only NameCallback, PasswordCallback and CredentialsCallback are supported by this handler.");
074            }
075        }
076    }
077
078}