Package org.waveprotocol.box.server.authentication

Source Code of org.waveprotocol.box.server.authentication.AccountStoreLoginModule

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.waveprotocol.box.server.authentication;

import com.google.common.base.Preconditions;

import org.waveprotocol.box.server.account.AccountData;
import org.waveprotocol.box.server.persistence.AccountStore;
import org.waveprotocol.box.server.persistence.PersistenceException;
import org.waveprotocol.wave.model.wave.InvalidParticipantAddress;
import org.waveprotocol.wave.model.wave.ParticipantId;
import org.waveprotocol.wave.util.logging.Log;

import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

/**
* A Simple login module which does username & password authentication against
* users in a database.
*
*  This code is based on the example here:
* http://java.sun.com/developer/technicalArticles/Security/jaasv2/
*
* @author josephg@gmail.com (Joseph Gentle)
*/
public class AccountStoreLoginModule implements LoginModule {
  private Subject subject;
  private ParticipantPrincipal principal;
  private CallbackHandler callbackHandler;
  private AccountStore accountStore;

  private final Log LOG = Log.get(AccountStoreLoginModule.class);
 
  enum Status {
    NOT, OK, COMMIT
  }

  private Status status;

  @Override
  public void initialize(Subject subject, CallbackHandler callbackHandler,
      Map<String, ?> sharedState, Map<String, ?> options) {
    Preconditions.checkNotNull(callbackHandler, "Callback handler null");

    accountStore = AccountStoreHolder.getAccountStore();

    status = Status.NOT;
    this.subject = subject;
    this.callbackHandler = callbackHandler;
  }

  @Override
  public boolean login() throws LoginException {
    NameCallback nameCallback = new NameCallback("Username");
    PasswordCallback passwordCallback = new PasswordCallback("Password", false);

    Callback callbacks[] = new Callback[] {nameCallback, passwordCallback};

    try {
      callbackHandler.handle(callbacks);
    } catch (java.io.IOException e) {
      throw new LoginException(e.toString());
    } catch (UnsupportedCallbackException e) {
      throw new LoginException("Error: " + e.getCallback().toString());
    }

    boolean success;
    ParticipantId id = null;
   
    String address = nameCallback.getName();
    if (!address.contains(ParticipantId.DOMAIN_PREFIX)) {
      address = address + ParticipantId.DOMAIN_PREFIX + AccountStoreHolder.getDefaultDomain();
    }
   
    try {
      id = ParticipantId.of(address);
      AccountData account = accountStore.getAccount(id);
      char[] password = passwordCallback.getPassword();
     
      if (account == null) {
        // The user doesn't exist. Auth failed.
        success = false;
      } else if (!account.isHuman()) {
        // The account is owned by a robot. Auth failed.
        success = false;
      } else if (password == null) {
        // Null password provided by callback. We require a password (even an empty one).
        success = false;
      } else if (!account.asHuman().getPasswordDigest().verify(password)) {
        // The supplied password doesn't match. Auth failed.
        success = false;
      } else {
        success = true;
      }
    } catch (InvalidParticipantAddress e) {
      // The supplied user address is invalid. Auth failed.
      success = false;
    } catch (PersistenceException e) {
      LOG.severe("Failed to retreive account data for " + id, e);
      throw new LoginException(
          "An unexpected error occured while trying to retrieve account information!");
    }

    // The password is zeroed before it gets GC'ed for memory security.
    passwordCallback.clearPassword();

    if (success) {
      principal = new ParticipantPrincipal(id);
      status = Status.OK;
      return true;
    } else {
      return false;
    }
  }

  @Override
  public boolean commit() {
    if (status == Status.NOT) {
      return false;
    }
    if (subject == null) {
      return false;
    }
    subject.getPrincipals().add(principal);
    status = Status.COMMIT;
    return true;
  }

  @Override
  public boolean abort() {
    if ((subject != null) && (principal != null)) {
      subject.getPrincipals().remove(principal);
    }
    principal = null;
    status = Status.NOT;
    return true;
  }

  @Override
  public boolean logout() {
    subject.getPrincipals().remove(principal);
    status = Status.NOT;
    return true;
  }
}
TOP

Related Classes of org.waveprotocol.box.server.authentication.AccountStoreLoginModule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.