Changeset 2258


Ignore:
Timestamp:
Feb 28, 2014, 11:02:46 AM (9 years ago)
Author:
Nicklas Nordborg
Message:

References #580: Authenticate users using YubiKey? sticks

Store YubiKey? information as extended properties instead of in the 'externalid' field.

Check regular password before verifying the YubiKey? password.

Location:
extensions/net.sf.basedb.yubikey/trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • extensions/net.sf.basedb.yubikey/trunk/src/net/sf/basedb/yubikey/YubiKey.java

    r2257 r2258  
    2525import java.net.URL;
    2626import java.util.Properties;
     27
     28import com.yubico.client.v2.YubicoClient;
    2729
    2830import net.sf.basedb.core.ConfigurationException;
     
    105107    return clientKey;
    106108  }
     109 
     110  /**
     111    Get a YubicoClient configured for verification of passwords.
     112  */
     113  public static YubicoClient getYubicoClient()
     114  {
     115    YubicoClient client = YubicoClient.getClient(getClientId());
     116    client.setKey(getClientKey());
     117    return client;
     118  }
    107119}
  • extensions/net.sf.basedb.yubikey/trunk/src/net/sf/basedb/yubikey/YubiKeyAuthenticationManager.java

    r2257 r2258  
    11package net.sf.basedb.yubikey;
    22
     3
     4import java.util.List;
    35
    46import com.yubico.client.v2.YubicoClient;
     
    79
    810import net.sf.basedb.core.AuthenticationContext;
     11import net.sf.basedb.core.Type;
    912import net.sf.basedb.core.authentication.AuthenticatedUser;
    1013import net.sf.basedb.core.authentication.AuthenticationManager;
     
    1215import net.sf.basedb.core.authentication.LoginRequest;
    1316import net.sf.basedb.core.data.UserData;
     17import net.sf.basedb.core.query.QueryParameter;
    1418
    1519/**
     
    5357    if (user != null)
    5458    {
    55       String externalId = user.getExternalId();
    56       if (externalId != null && externalId.startsWith("YubiKey:"))
     59      String yubiKeyId = (String)user.getExtended("yubiKeyId");
     60      if (yubiKeyId != null)
    5761      {
    5862        throw new LoginException("User '" + login + "' must login with YubiKey!");
     
    6569    if (YubicoClient.isValidOTPFormat(login))
    6670    {
    67       // Find user in BASE with externalId=YubiKey:<public-id>
     71      // Find user(s) in BASE with yubiKeyId=<public-id>
    6872      String publicId = YubicoClient.getPublicId(login);
    69       String externalId = "YubiKey:" + publicId;
    70       user = context.getUserByExternalId(externalId);
    71    
     73      QueryParameter qp = new QueryParameter("ykId", false, Type.STRING, publicId);
     74      List<UserData> users = context.findUsers("yubiKeyId=:ykId", qp);
     75     
     76      if (users.size() > 0)
     77      {
     78        // Check the password for each of the users in the list
     79        // Normally, a single user is found, but theoretically it is
     80        // possible to assign the same YubiKey yto multiple accounts if
     81        // they have different password
     82        RuntimeException loginFailed = null;
     83        for (UserData u : users)
     84        {
     85          LoginRequest internal = new LoginRequest(u.getId(), request.getPassword());
     86          try
     87          {
     88            context.verifyUserInternal(internal);
     89            // If we get here, the password is ok and we break out of the loop
     90            user = u;
     91            break;
     92          }
     93          catch (RuntimeException ex)
     94          {
     95            // Save the first exception so we can re-throw it later if needed
     96            if (loginFailed == null) loginFailed = ex;
     97          }
     98        }
     99        // If no user with correct password was found we re-throw the first exception
     100        if (user == null && loginFailed != null)
     101        {
     102          throw loginFailed;
     103        }
     104      }
     105     
    72106      if (user != null)
    73107      {
     
    77111        try
    78112        {
    79           ybClient = YubicoClient.getClient(YubiKey.getClientId());
    80           ybClient.setKey(YubiKey.getClientKey());
    81           response = ybClient.verify(login);
     113          YubicoClient client = YubiKey.getYubicoClient();
     114          response = client.verify(login);
    82115        }
    83116        catch (Exception e)
     
    87120       
    88121        YubicoResponseStatus status = response.getStatus();
    89         /*
    90         System.out.println("status:" + response.getStatus());
    91         System.out.println("H:" + response.getH());
    92         System.out.println("Nonce:" + response.getNonce());
    93         System.out.println("otp:" + response.getOtp());
    94         //System.out.println("publicid:" + response.getPublicId());
    95         System.out.println("sessioncounter:" + response.getSessioncounter());
    96         System.out.println("sessionuse:" + response.getSessionuse());
    97         System.out.println("Sl:" + response.getSl());
    98         System.out.println("T:" + response.getT());
    99         System.out.println("Timestamp:" + response.getTimestamp());
    100         */
    101 
    102122        if (status != YubicoResponseStatus.OK)
    103123        {
     
    114134        }
    115135
    116         // YubiKey is valid -- verify password using internal authentication
    117         LoginRequest internal = new LoginRequest(user.getLogin(), request.getPassword());
    118         context.verifyUserInternal(internal);
     136        // YubiKey is valid -- the user is allowed to access BASE!
    119137        authInfo = new AuthenticatedUser(YubiKey.AUTHENTICATION_METHOD, user);
    120138      }
Note: See TracChangeset for help on using the changeset viewer.