com.launchkey.example.springmvc.AuthManager Maven / Gradle / Ivy
/**
* Copyright 2016 LaunchKey, Inc. All rights reserved.
*
* Licensed under the MIT License.
* You may not use this file except in compliance with the License.
* A copy of the License is located in the "LICENSE.txt" file accompanying
* this file. This file 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 com.launchkey.example.springmvc;
import com.launchkey.sdk.AppClient;
import com.launchkey.sdk.ClientFactoryBuilder;
import com.launchkey.sdk.domain.auth.AuthResponse;
import com.launchkey.sdk.domain.auth.AuthResponseCallbackResponse;
import com.launchkey.sdk.domain.auth.CallbackResponse;
import com.launchkey.sdk.domain.auth.LogoutCallbackResponse;
import com.launchkey.sdk.error.BaseException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import javax.naming.ConfigurationException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class AuthManager {
final Logger log = LoggerFactory.getLogger(getClass());
private final com.launchkey.sdk.service.application.auth.AuthService authService;
private final Map sessionAuthRequestMap;
private final Map sessionAuthenticationMap;
private final Map> userHashSessionMap;
@SuppressWarnings("ThrowFromFinallyBlock")
@Autowired
public AuthManager(PlatformSdkConfig appConfig) throws ConfigurationException, IOException {
final Long appKey = appConfig.getAppKey();
final String secretKey = appConfig.getSecretKey();
final String privateKeyLocation = appConfig.getPrivateKeyLocation();
final String baseURL = appConfig.getBaseUrl();
boolean halt = false;
if (appKey == null) {
log.error("mfa.app-key property not provided");
halt = true;
}
if (secretKey == null) {
log.error("mfa.secret-key property not provided");
halt = true;
}
if (privateKeyLocation == null) {
log.error("mfa.private-key-location property not provided");
halt = true;
}
if (halt) throw new ConfigurationException("Missing required mfa configuration");
BufferedReader br = new BufferedReader(new FileReader(privateKeyLocation));
StringBuilder sb = new StringBuilder();
try {
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append("\n");
line = br.readLine();
}
} finally {
br.close();
}
String privateKey = sb.toString();
ClientFactoryBuilder builder = new ClientFactoryBuilder()
.setJCEProvider(new BouncyCastleProvider());
if (baseURL != null) {
builder.setAPIBaseURL(baseURL);
}
AppClient client = builder.build().makeAppClient(appKey, secretKey, privateKey);
this.authService = client.auth();
this.sessionAuthenticationMap = Collections.synchronizedMap(new HashMap());
this.sessionAuthRequestMap = new ConcurrentHashMap();
this.userHashSessionMap = new ConcurrentHashMap>();
}
public void login(String username, String context) throws AuthException {
try {
String authRequestId = this.authService.login(username, context);
String sessionId = getSessionId();
sessionAuthRequestMap.put(sessionId, authRequestId);
sessionAuthenticationMap.put(sessionId, null);
} catch (BaseException apiException) {
throw new AuthException("Error logging in with username: " + username, apiException);
}
}
public Boolean isAuthorized() throws AuthException {
String sessionId = getSessionId();
if (sessionAuthenticationMap.containsKey(sessionId)) {
return sessionAuthenticationMap.get(sessionId);
} else {
throw new AuthException("No auth request found for this session");
}
}
public void logout(String sessionId) throws AuthException {
if (sessionAuthenticationMap.get(sessionId)) {
sessionAuthenticationMap.put(sessionId, false);
if (sessionAuthRequestMap.containsKey(sessionId)) {
try {
authService.logout(sessionAuthRequestMap.get(sessionId));
sessionAuthenticationMap.put(sessionId, false);
sessionAuthRequestMap.remove(sessionId);
} catch (BaseException apiException) {
throw new AuthException(
"Error on logout for auth request: " + sessionAuthRequestMap.get(sessionId),
apiException
);
}
} else {
throw new AuthException("No auth request found for this session");
}
}
}
public void handleCallback(Map callbackData) throws AuthException {
try {
CallbackResponse callbackResponse = authService.handleCallback(callbackData, 300);
if (callbackResponse instanceof AuthResponseCallbackResponse) {
AuthResponse authResponse = ((AuthResponseCallbackResponse) callbackResponse).getAuthResponse();
String authRequestId = authResponse.getAuthRequestId();
String sessionId = null;
for (Map.Entry entry : sessionAuthRequestMap.entrySet()) {
if (entry.getValue().equals(authRequestId)) {
sessionId = entry.getKey();
break;
}
}
if (null == sessionId) {
throw new AuthException("No session found for auth request: " + authRequestId);
}
sessionAuthenticationMap.put(sessionId, authResponse.isAuthorized());
List sessionList = userHashSessionMap.get(authResponse.getUserHash());
if (null == sessionList) { // If no session list exists for the user hash, create one in the map
sessionList = Collections.synchronizedList(new ArrayList());
userHashSessionMap.put(authResponse.getUserHash(), sessionList);
}
// If the session does not already exist in the session list add it
if (!sessionList.contains(sessionId)) {
sessionList.add(sessionId);
}
} else if (callbackResponse instanceof LogoutCallbackResponse) {
String userHash = ((LogoutCallbackResponse) callbackResponse).getUserHash();
for (String sessionId : userHashSessionMap.get(userHash)) {
logout(sessionId);
}
userHashSessionMap.remove(userHash);
}
} catch (BaseException apiException) {
throw new AuthException("Error handling callback", apiException);
}
}
public void transitionSession(String oldSessionId, String newSessionId) {
sessionAuthenticationMap.put(newSessionId, sessionAuthenticationMap.get(oldSessionId));
sessionAuthenticationMap.remove(oldSessionId);
sessionAuthRequestMap.put(newSessionId, sessionAuthRequestMap.get(oldSessionId));
sessionAuthRequestMap.remove(oldSessionId);
for (Map.Entry> entry : userHashSessionMap.entrySet()) {
List sessions = entry.getValue();
if (sessions.contains(oldSessionId)) {
sessions.add(newSessionId);
sessions.remove(oldSessionId);
}
}
}
private String getSessionId() {
return RequestContextHolder.currentRequestAttributes().getSessionId();
}
public class AuthException extends Throwable {
public AuthException(String message) {
super(message);
}
public AuthException(String message, Throwable cause) {
super(message, cause);
}
}
}