I am using the MobileFirst UserLogin
sample adapter for SecurityCheck. I want to implement Single Sign On (SSO)
With the clean adapter downloaded from Github, SSO works fine. But I want to validate the credentials against a mysql database. I have noticed that as soon as I add the line
dataSource = new BasicDataSource();
in validateCredentials
method, the SSO stops working:
@Override
protected boolean validateCredentials(Map<String, Object> credentials) {
if(credentials!=null && credentials.containsKey("username") && credentials.containsKey("password")){
String username = credentials.get("username").toString();
String password = credentials.get("password").toString();
dataSource = new BasicDataSource(); //this line
if(!username.isEmpty() && !password.isEmpty() && username.equals(password)) {
...
I can still login using this adapter, but SSO does not work anymore.
Complete adapter:
adapter.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<mfp:adapter name="UserLogin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mfp="http://www.ibm.com/mfp/integration"
xmlns:http="http://www.ibm.com/mfp/integration/http">
<displayName>UserLogin</displayName>
<description>Protect resources using a combination of username and password.</description>
<securityCheckDefinition name="UserLogin" class="com.sample.UserLogin">
<property name="maxAttempts" defaultValue="3" description="How many attempts are allowed" type="integer"/>
<property name="blockedStateExpirationSec" defaultValue="10" description="How long before the client can try again (seconds)" type="integer"/>
<property name="successStateExpirationSec" defaultValue="60" description="How long is a successful state valid for (seconds)" type="integer"/>
<property name="rememberMeDurationSec" defaultValue="120" description="How long is the user remembered when using RememberMe (seconds)" type="integer"/>
</securityCheckDefinition>
</mfp:adapter>
UserLogin.java
:
package com.sample;
import com.ibm.mfp.security.checks.base.UserAuthenticationSecurityCheck;
import com.ibm.mfp.server.registration.external.model.AuthenticatedUser;
import org.apache.commons.dbcp.BasicDataSource;
import java.util.HashMap;
import java.util.Map;
import java.sql.*;
public class UserLogin extends UserAuthenticationSecurityCheck {
private String userId, displayName;
private String errorMsg;
private boolean rememberMe = false;
public BasicDataSource dataSource = null;
@Override
protected AuthenticatedUser createUser() {
return new AuthenticatedUser(userId, displayName, this.getName());
}
@Override
protected boolean validateCredentials(Map<String, Object> credentials) {
if(credentials!=null && credentials.containsKey("username") && credentials.containsKey("password")){
String username = credentials.get("username").toString();
String password = credentials.get("password").toString();
dataSource = new BasicDataSource();
if(!username.isEmpty() && !password.isEmpty() && username.equals(password)) {
userId = username;
displayName = username;
//Optional RememberMe
if(credentials.containsKey("rememberMe") ){
rememberMe = Boolean.valueOf(credentials.get("rememberMe").toString());
}
errorMsg = null;
return true;
}
else {
errorMsg = "Wrong Credentials";
}
}
else{
errorMsg = "Credentials not set properly";
}
return false;
}
@Override
protected Map<String, Object> createChallenge() {
Map challenge = new HashMap();
challenge.put("errorMsg",errorMsg);
challenge.put("remainingAttempts",getRemainingAttempts());
return challenge;
}
@Override
protected boolean rememberCreatedUser() {
return rememberMe;
}
}
pom.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>UserLogin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>adapter</packaging>
<name>UserLogin</name>
<dependencies>
<dependency>
<groupId>com.ibm.mfp</groupId>
<artifactId>adapter-maven-api</artifactId>
<scope>provided</scope>
<version>[8.0.0,9.0.0)</version>
</dependency>
<dependency>
<groupId>com.ibm.mfp</groupId>
<artifactId>mfp-security-checks-base</artifactId>
<version>[8.0.0,9.0.0)</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
<properties>
<!-- Use UTF-8 as the encoding of the adapter -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- parameters for deploy mfpf adapter -->
<mfpfUrl>http://localhost:9080/mfpadmin</mfpfUrl>
<mfpfUser>admin</mfpfUser>
<mfpfPassword>admin</mfpfPassword>
<mfpfRuntime>mfp</mfpfRuntime>
<mfpfRuntime>mfp</mfpfRuntime>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.ibm.mfp</groupId>
<artifactId>adapter-maven-plugin</artifactId>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
</project>
Use BasicDataSource as transient. Basically when you implement MFP security check, any object that you would not need to as part of Security Check, mark them transient to ensure it is not getting saved as a part of securitycheck state.