I am using wso2 IS 5.10, for adding custom claim which needs to be added by fetching from db I am using custom adaptive function. But the below code is not working.
package org.wso2.custom.auth.functions;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.JsAuthenticationContext;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import org.wso2.custom.auth.functions.internal.CustomAuthFuncComponent;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.js.*;
public class SetForceAuthFunctionImpl implements SetForceAuthFunction {
private static final Log LOGGER = LogFactory.getLog(SetForceAuthFunctionImpl.class);
#Override
public JsAuthenticatedUser setForceAuth(JsAuthenticationContext context, boolean forceAuth) {
AuthenticatedUser lastAuthenticatedUser = context.getContext().getLastAuthenticatedUser();
LOGGER.info("lastAuthenticatedUser****:::::::::::"+lastAuthenticatedUser);
String userName = lastAuthenticatedUser.getUserName();
LOGGER.info("userName2****:::::::::::"+userName);
String tenantDomain = MultitenantUtils.getTenantDomain(userName);
String fullyQualifiedUserName=("USERS"+"/"+userName+"#"+tenantDomain);
Map<org.wso2.carbon.identity.application.common.model.ClaimMapping, String> claims = new HashMap<org.wso2.carbon.identity.application.common.model.ClaimMapping, String>();
claims.put(org.wso2.carbon.identity.application.common.model.ClaimMapping.build("test123", "test123", null, true), org.apache.commons.lang3.StringUtils.join("*******************",",,,"));
AuthenticatedUser authenticatedUserObj = AuthenticatedUser.createLocalAuthenticatedUserFromSubjectIdentifier(MultitenantUtils.getTenantAwareUsername
(fullyQualifiedUserName));
authenticatedUserObj.setAuthenticatedSubjectIdentifier(MultitenantUtils.getTenantAwareUsername
(fullyQualifiedUserName));
authenticatedUserObj.setUserAttributes(claims);
authenticatedUserObj.setUserName(MultitenantUtils.getTenantAwareUsername
(fullyQualifiedUserName));
return new JsAuthenticatedUser(authenticatedUserObj);
}
}
package org.wso2.custom.auth.functions.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.wso2.carbon.identity.application.authentication.framework.JsFunctionRegistry;
import org.wso2.carbon.registry.core.service.RegistryService;
import org.wso2.carbon.user.core.service.RealmService;
import org.wso2.custom.auth.functions.GenerateHashFunction;
import org.wso2.custom.auth.functions.GenerateHashFunctionImpl;
import org.wso2.custom.auth.functions.GetClaimsForUsernameFunction;
import org.wso2.custom.auth.functions.GetClaimsForUsernameFunctionImpl;
import org.wso2.custom.auth.functions.GetUsernameFromContextFunction;
import org.wso2.custom.auth.functions.GetUsernameFromContextFunctionImpl;
import org.wso2.custom.auth.functions.SetForceAuthFunction;
import org.wso2.custom.auth.functions.SetForceAuthFunctionImpl;
#Component(
name = "custom.auth.functions.component",
immediate = true
)
public class CustomAuthFuncComponent {
private static final Log LOG = LogFactory.getLog(CustomAuthFuncComponent.class);
private static JsFunctionRegistry jsFunctionRegistry;
#Activate
protected void activate(ComponentContext ctxt) {
SetForceAuthFunction setForceAuthFunctionImpl = new SetForceAuthFunctionImpl();
jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "setForceAuth",
setForceAuthFunctionImpl);
GetUsernameFromContextFunction getUsernameFromContextFunctionImpl = new GetUsernameFromContextFunctionImpl();
jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getUsernameFromContext",
getUsernameFromContextFunctionImpl);
GetClaimsForUsernameFunction getClaimsForUsernameFunctionImpl = new GetClaimsForUsernameFunctionImpl();
jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getClaimsForUsername",
getClaimsForUsernameFunctionImpl);
GenerateHashFunction generateHashFunctionImpl = new GenerateHashFunctionImpl();
jsFunctionRegistry.register(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "generateHash",
generateHashFunctionImpl);
}
#Deactivate
protected void deactivate(ComponentContext ctxt) {
if (jsFunctionRegistry != null) {
jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "setForceAuth");
jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getUsernameFromContext");
jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "getClaimsForUsername");
jsFunctionRegistry.deRegister(JsFunctionRegistry.Subsystem.SEQUENCE_HANDLER, "generateHash");
}
}
#Reference(
name = "user.realmservice.default",
service = RealmService.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetRealmService"
)
protected void setRealmService(RealmService realmService) {
if (LOG.isDebugEnabled()) {
LOG.debug("RealmService is set in the custom conditional authentication user functions bundle");
}
CustomAuthFuncHolder.getInstance().setRealmService(realmService);
}
protected void unsetRealmService(RealmService realmService) {
if (LOG.isDebugEnabled()) {
LOG.debug("RealmService is unset in the custom conditional authentication user functions bundle");
}
CustomAuthFuncHolder.getInstance().setRealmService(null);
}
#Reference(
name = "registry.service",
service = RegistryService.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetRegistryService"
)
protected void setRegistryService(RegistryService registryService) {
if (LOG.isDebugEnabled()) {
LOG.debug("RegistryService is set in the custom conditional authentication user functions bundle");
}
CustomAuthFuncHolder.getInstance().setRegistryService(registryService);
}
protected void unsetRegistryService(RegistryService registryService) {
if (LOG.isDebugEnabled()) {
LOG.debug("RegistryService is unset in the custom conditional authentication user functions bundle");
}
CustomAuthFuncHolder.getInstance().setRegistryService(null);
}
#Reference(
service = JsFunctionRegistry.class,
cardinality = ReferenceCardinality.MANDATORY,
policy = ReferencePolicy.DYNAMIC,
unbind = "unsetJsFunctionRegistry"
)
public void setJsFunctionRegistry(JsFunctionRegistry jsFunctionRegistry) {
this.jsFunctionRegistry = jsFunctionRegistry;
}
public void unsetJsFunctionRegistry(JsFunctionRegistry jsFunctionRegistry) {
this.jsFunctionRegistry = null;
}
}
But when I am using setForceAuth(context, true); in adaptive authentication function to add custom claims its not working but working in custom authenticator.
Adaptive authentication script:
function onLoginRequest(context) {
doLogin(context);
}
function doLogin(context) {
executeStep(1,{
onSuccess: function (context) {
},
onFail: function(context){
executeStep(4,{
onSuccess: function (context) {
var subject = context.currentKnownSubject;
setForceAuth(context, true);
},
onFail: function(context){
}
});
}
});
}
The issue is that
setForceAuth(context, true);
executes the below code block
return new JsAuthenticatedUser(authenticatedUserObj);
There is no point in your code (authencation script or the java function) where the newly created JsAuthenticatedUser is set to the context.
What you need to do is to change the script like this
onSuccess: function (context) { context.currentKnownSubject = setForceAuth(context, true);}
or
the java function as below
`#Override
public JsAuthenticatedUser setForceAuth(JsAuthenticationContext context, boolean forceAuth) {
AuthenticatedUser lastAuthenticatedUser = context.getContext().getLastAuthenticatedUser();
LOGGER.info("lastAuthenticatedUser****:::::::::::"+lastAuthenticatedUser);
String userName = lastAuthenticatedUser.getUserName();
LOGGER.info("userName2****:::::::::::"+userName);
String tenantDomain = MultitenantUtils.getTenantDomain(userName);
String fullyQualifiedUserName=("USERS"+"/"+userName+"#"+tenantDomain);
Map<org.wso2.carbon.identity.application.common.model.ClaimMapping, String> claims = new HashMap<org.wso2.carbon.identity.application.common.model.ClaimMapping, String>();
claims.put(org.wso2.carbon.identity.application.common.model.ClaimMapping.build("test123", "test123", null, true), org.apache.commons.lang3.StringUtils.join("*******************",",,,"));
AuthenticatedUser authenticatedUserObj = AuthenticatedUser.createLocalAuthenticatedUserFromSubjectIdentifier(MultitenantUtils.getTenantAwareUsername
(fullyQualifiedUserName));
authenticatedUserObj.setAuthenticatedSubjectIdentifier(MultitenantUtils.getTenantAwareUsername
(fullyQualifiedUserName));
authenticatedUserObj.setUserAttributes(claims);
authenticatedUserObj.setUserName(MultitenantUtils.getTenantAwareUsername
(fullyQualifiedUserName));
context.getContext().setSubject(authenticatedUserObj);
}
Still it is not advisable to have a tenant aware user name on authentication scripts. Rather can you think of not using
setForceAuth()
function and use the provided user.localClaims[] instead?
Related
I am developing a app in flutter and I am having a problem with detecting a locks via tapkey mobile sdk. I am login users with Token Exchange method, I have created new Identity Providers. I am creating a new user via a cloud function (Owners/{ownerAccountId}/IdentityProviders/{ipId}/Users however i'm not adding the contact) using the Client Credentials that i have also added to my.tapkey.com as new user and assigned a lock to it.
I can successfully run logInAsync with the token i am receiving via Token Exchange however when i try to find a nearby locks i got {} as a response (i will mention that the lock is next to me).
my code:
import android.Manifest
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import com.tapkey.mobile.TapkeyAppContext
import com.tapkey.mobile.TapkeyEnvironmentConfigBuilder
import com.tapkey.mobile.TapkeyServiceFactory
import com.tapkey.mobile.TapkeyServiceFactoryBuilder
import com.tapkey.mobile.ble.BleLockScanner
import com.tapkey.mobile.concurrent.CancellationToken
import com.tapkey.mobile.concurrent.CancellationTokenSource
import com.tapkey.mobile.manager.UserManager
import io.flutter.app.FlutterApplication
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.FlutterEngineCache
import io.flutter.embedding.engine.dart.DartExecutor
import net.tpky.mc.time.ServerClock
import org.json.JSONObject
import java.net.HttpURLConnection
import java.net.URL
class TapKeyTest : FlutterApplication(), TapkeyAppContext {
private lateinit var tapkeyServiceFactory: TapkeyServiceFactory
lateinit var flutterEngine: FlutterEngine
companion object {
const val FLUTTER_ENGINE_NAME = "nps_flutter_engine_name"
}
override fun onCreate() {
super.onCreate()
flutterEngine = FlutterEngine(this)
flutterEngine.dartExecutor.executeDartEntrypoint(
DartExecutor.DartEntrypoint.createDefault()
)
FlutterEngineCache
.getInstance()
.put(FLUTTER_ENGINE_NAME, flutterEngine)
val serverClock = ServerClock()
val config = TapkeyEnvironmentConfigBuilder()
config.setBaseUri("https://my.tapkey.com/")
val b = TapkeyServiceFactoryBuilder(this )
.setServerClock(serverClock)
.setConfig(config.build())
val sf = b.build()
tapkeyServiceFactory = sf
}
override fun getTapkeyServiceFactory(): TapkeyServiceFactory {
return tapkeyServiceFactory
}
fun login(SECRET_TOKEN: String) {
val src = CancellationTokenSource()
val ct: CancellationToken = src.token
val userManager: UserManager = tapkeyServiceFactory.userManager
userManager.logInAsync(SECRET_TOKEN, ct)
.continueOnUi { userId -> scanLocks()}
.catchOnUi { asyncError -> println(asyncError.cause) } }
private fun scanLocks( ) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_SCAN
) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(
this,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
return
} else {
tapkeyServiceFactory.bleLockScanner.locksChangedObservable
.addObserver { locks -> println(locks)}
println( tapkeyServiceFactory.bleLockScanner.locks)
println("Permission granted")
}
}
}
Is there a step that i have missed? Also i can't find anywhere new users that i am creating.
It seems, that you don't start the scanning:
BleLockScanner scanner = tapkeyServiceFactory.getBleLockScanner();
bleScanObserverRegistration = scanner.startForegroundScan();
I have 2 restful service method getCustomerJson and getCustomerXML in a class CustomerResource where i am using jersey API for Restful Webservices. All the parameters of the 2 methods are same except one produces xml and other produces json.
When i am using the a HTTP GET request with header Content-Type="application/json" it always invokes the getCustomerXML method which returns xml.
Can someone explain me how jersey works in this kind of situation ?
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import domain.Customer;
#Path("/customers")
public class CustomerResource {
private static Map<Integer, Customer> customerDB = new ConcurrentHashMap<Integer, Customer>();
private static AtomicInteger idCounter = new AtomicInteger();
// Constructor
public CustomerResource() {
}
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
return "Hello Kundan !!!";
}
#GET
#Path("{id}")
#Produces("application/xml")
public Customer getCustomerXML(#PathParam("id") int id, #Context HttpHeaders header) {
final Customer customer = customerDB.get(id);
List<String> contentList = header.getRequestHeader("Content-Type");
List<String> languageList = header.getRequestHeader("Accept-Language");
List<String> compressionFormatList = header.getRequestHeader("Content-Type");
if (customer == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return customer;
}
#GET
#Path("{id}")
#Produces("application/json")
public Customer getCustomerJson(#PathParam("id") int id) {
final Customer customer = customerDB.get(id);
if (customer == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return customer;
}
#POST
#Consumes("application/xml")
public Response createCustomer(Customer customer) {
customer.setId(idCounter.incrementAndGet());
customerDB.put(customer.getId(), customer);
System.out.println("Created customer " + customer.getId());
return Response.created(URI.create("/customers/" + customer.getId())).build();
}
#PUT
#Path("{id}")
#Consumes("application/xml")
public void updateCustomer(#PathParam("id") int id, Customer customer) {
Customer current = customerDB.get(id);
if (current == null)
throw new WebApplicationException(Response.Status.NOT_FOUND);
current.setFirstName(customer.getFirstName());
current.setLastName(customer.getLastName());
current.setStreet(customer.getStreet());
current.setCity(customer.getCity());
current.setState(customer.getState());
current.setZip(customer.getZip());
current.setCountry(customer.getCountry());
}
#DELETE
#Path("{id}")
public void deleteCustomer(#PathParam("id") int id) {
customerDB.remove(id);
System.out.println("Deleted !");
}
}
Use Accept: application/json. Accept tells the server what type you want back. Content-Type if for the type of data you are sending to the server, like with a POST request.
I'm using the developer-authenticated technique for implementing this class, as described here. So far, I've been able to implement this class and build a framework in which I check CognitoCachingCredentialsProvider.getCachedIdentityId() to see if a user has logged in (and therefore doesn't need to re-authenticate by entering an email and password). To do this, I'm using a series of static methods in a class called Util, since these only need to be instantiated once. This is what it looks like:
package com.pranskee.boxesapp;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.util.Log;
import com.amazonaws.auth.AWSAbstractCognitoIdentityProvider;
import com.amazonaws.auth.CognitoCachingCredentialsProvider;
import com.amazonaws.mobileconnectors.cognito.*;
import com.amazonaws.regions.Regions;
public class Util {
private final static String TAG = "Util";
private static final String AWS_ACCOUNT_ID = {acct id};
private static final String COGNITO_POOL_ID = {pool id};
private static final String COGNITO_ROLE_AUTH = {auth arn};
private static final String COGNITO_ROLE_UNAUTH = {unauth arn}
private static CognitoCachingCredentialsProvider sCredProvider;
private static UserIdentityProvider sIdProvider;
private static CognitoSyncManager sSyncManager;
private Util() {
}
public static CognitoCachingCredentialsProvider getCredProvider(
Context context) {
if (sCredProvider == null) {
if (sIdProvider == null) {
CognitoCachingCredentialsProvider tmpProvider = new CognitoCachingCredentialsProvider(
context.getApplicationContext(), AWS_ACCOUNT_ID,
COGNITO_POOL_ID, COGNITO_ROLE_UNAUTH,
COGNITO_ROLE_AUTH, Regions.US_EAST_1);
if (tmpProvider.getCachedIdentityId() != null) {
sCredProvider = tmpProvider;
} else {
sCredProvider = null;
}
} else {
sCredProvider = new CognitoCachingCredentialsProvider(
context.getApplicationContext(), sIdProvider,
COGNITO_ROLE_UNAUTH, COGNITO_ROLE_AUTH);
}
}
return sCredProvider;
}
public static UserIdentityProvider getIdentityProvider(Context context,
String email, String pwd) {
if (sIdProvider == null) {
sIdProvider = new UserIdentityProvider(AWS_ACCOUNT_ID,
COGNITO_POOL_ID, context.getApplicationContext(), email,
pwd);
Map logins = new HashMap();
logins.put({Developer Provider Name}, sIdProvider.getToken());
sIdProvider.setLogins(logins);
}
return sIdProvider;
}
public static boolean isLoggedIn(Context context) {
if (getCredProvider(context) == null) {
return false;
}
return true;
}
private static CognitoSyncManager getSyncManager(Context context) {
if (sSyncManager == null) {
sSyncManager = new CognitoSyncManager(
context.getApplicationContext(), Regions.US_EAST_1,
sCredProvider);
}
return sSyncManager;
}
protected static class UserIdentityProvider extends
AWSAbstractCognitoIdentityProvider {
private Context context;
private String email;
private String password;
public UserIdentityProvider(String accountId, String identityPoolId,
Context c, String em, String pwd) {
super(accountId, identityPoolId);
context = c;
email = em;
password = pwd;
}
#Override
public String refresh() {
try {
ServerCommunicator server = new ServerCommunicator(context);
//this is a server call, which makes the call GetOpenIdTokenForDeveloperIdentityRequest after I authenticate the user and send AWS my user's token
String response = server.initUserLoginAsyncTask()
.execute(email, password).get();
JSONObject responseJSON = new JSONObject(response);
String identityId = responseJSON.getString("id");
String token = responseJSON.getString("token");
this.setToken(token);
this.setIdentityId(identityId);
update(identityId, token);
return token;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
public String getProviderName() {
return {Developer Provider Name};
}
}
}
Now, I want to also implement a Logout. I think what I'd need to do is remove the cached Identity Id somehow, but I'm not sure what the best method would be to do that. Or, maybe it's not that at all, and I need to do something differently entirely. Either way, I just want to implement the intended behavior of allowing a user to select to "Log Out" of my app, which causes Cognito to forget that that ID was logged into the Identity Pool and invalidates any attempt to establish an Identity ID again without going through my authentication process again.
Logout would be a two steps process, first you need to logout from the Identity Provider that authenticated your user (Amazon, Google, Facebook or your own) Instructions on how to do this are specific to your provider.
From the CognitoIdentity side, you need to tell the CredentialsProvider to clear all state and cache associated with your identity. Using Android SDK, you can call clear() on the CredentialsProvider (see http://docs.aws.amazon.com/AWSAndroidSDK/latest/javadoc/com/amazonaws/auth/CognitoCredentialsProvider.html)
I might be misunderstanding the intended behavior of this method, but this is what I am trying to use it for:
-User logs in successfully
-User closes app completely (closes in background as well)
-User opens app again and doesn't have to log in again because CognitoCachingCredentialsProvider can check locally on the device to see she's still logged in
The way I tried to accomplish this is to check, before being prompted to log in, what getCachedIdentityId() returns. If it returns not null, then that means that she's still logged in, because there was nothing that cleared her credentials from the device. Here's what my framework looks like. I'm using developer authenticated method:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.util.Log;
import com.amazonaws.auth.AWSAbstractCognitoIdentityProvider;
import com.amazonaws.auth.CognitoCachingCredentialsProvider;
import com.amazonaws.mobileconnectors.cognito.*;
import com.amazonaws.regions.Regions;
public class Util {
private final static String TAG = "Util";
private static final String AWS_ACCOUNT_ID = {acct id};
private static final String COGNITO_POOL_ID = {pool id};
private static final String COGNITO_ROLE_AUTH = {auth arn};
private static final String COGNITO_ROLE_UNAUTH = {unauth arn}
private static CognitoCachingCredentialsProvider sCredProvider;
private static UserIdentityProvider sIdProvider;
private static CognitoSyncManager sSyncManager;
private Util() {
}
public static CognitoCachingCredentialsProvider getCredProvider(
Context context) {
if (sCredProvider == null) {
if (sIdProvider == null) {
CognitoCachingCredentialsProvider tmpProvider = new CognitoCachingCredentialsProvider(
context.getApplicationContext(), AWS_ACCOUNT_ID,
COGNITO_POOL_ID, COGNITO_ROLE_UNAUTH,
COGNITO_ROLE_AUTH, Regions.US_EAST_1);
if (tmpProvider.getCachedIdentityId() != null) {
sCredProvider = tmpProvider;
} else {
sCredProvider = null;
}
} else {
sCredProvider = new CognitoCachingCredentialsProvider(
context.getApplicationContext(), sIdProvider,
COGNITO_ROLE_UNAUTH, COGNITO_ROLE_AUTH);
Map logins = new HashMap();
logins.put({Developer Provider Name}, sIdProvider.getToken());
sCredProvider.setLogins(logins);
}
}
return sCredProvider;
}
public static UserIdentityProvider getIdentityProvider(Context context,
String email, String pwd) {
if (sIdProvider == null) {
sIdProvider = new UserIdentityProvider(AWS_ACCOUNT_ID,
COGNITO_POOL_ID, context.getApplicationContext());
}
return sIdProvider;
}
public static boolean isLoggedIn(Context context) {
if (getCredProvider(context) == null) {
return false;
}
return true;
}
protected static class UserIdentityProvider extends
AWSAbstractCognitoIdentityProvider {
private Context context;
private String email;
private String password;
public UserIdentityProvider(String accountId, String identityPoolId,
Context c) {
super(accountId, identityPoolId);
context = c;
email = em;
password = pwd;
}
#Override
public String refresh() {
try {
ServerCommunicator server = new ServerCommunicator(context);
if (email != null && password != null) {
//this is a server call, which makes the call GetOpenIdTokenForDeveloperIdentityRequest after I authenticate the user and send AWS my user's token
String response = server.initUserLoginAsyncTask()
.execute(email, password).get();
prefs.setAllUserSharedPrefs(response);
JSONObject responseJSON = new JSONObject(response);
String identityId = responseJSON.getString("id");
String token = responseJSON.getString("token");
if (token != null && identityId != null) {
this.setToken(token);
this.setIdentityId(identityId);
update(identityId, token);
return token;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
public String getProviderName() {
return {Developer Provider Name};
}
}
}
I simply call the isLoggedIn method from this class to see if there's an IdentityId stored locally. However, this isn't working as expected. I can see from debugging that getCachedIdentityId is always null (even directly after initializing CognitoCachingCredentialsProvider and adding the token to the logins map) and I am always prompted to log in again whenever I open the app after it has been closed. When does the IdentityId actually get stored locally and is my logic correct in general?
Additional Code
import java.util.concurrent.ExecutionException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class LoginActivity extends Activity {
private final String TAG = "LoginActivity";
private EditText etEmail, etPwd;
private Button bLogin, bGoToRegister;
private ServerCommunicator server;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate");
server = new ServerCommunicator(this);
if (Util.isLoggedIn(this)) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
return;
}
this.setContentView(R.layout.activity_login);
etEmail = (EditText) findViewById(R.id.etEmail);
etPwd = (EditText) findViewById(R.id.etPassword);
bLogin = (Button) findViewById(R.id.bLogin);
bGoToRegister = (Button) findViewById(R.id.bGoToRegister);
bLogin.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String email = etEmail.getText().toString();
String pwd = etPwd.getText().toString();
Util.getIdentityProvider(v.getContext()).setEmail(email);
Util.getIdentityProvider(v.getContext()).setPassword(pwd);
String token = Util.getIdentityProvider(v.getContext()).refresh();
if (token != null) {
Intent intent = new Intent(v.getContext(), MainActivity.class);
startActivity(intent);
} else {
Toast.makeText(v.getContext(), "Invalid username/password",
Toast.LENGTH_SHORT).show();
}
}
});
}
}
The above is my LoginActivity. When the app starts the MainActivity, I have the following snippet at the beginning of my onCreate method:
if (!Util.isLoggedIn(this)) {
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
}
This call initializes the CognitoCachingCredentialsProvider. I assumed that this would be when the IdentityId gets cached, but my debugging has revealed that even directly after this block, getCachedIdentityId() still returns null. Am I way off base with how I'm trying to use this class?
I have one suggestion. The CognitoCachingCredentialsProvider is what saves the identityId as it's changed. It doesn't start listening, though, until it's been initialized, and the change occurs on refresh call to your identity provider.
Can you try moving the initialization of the CognitoCachingCredentialsProvider to before the refresh call (but after your identity provider initialization)?
Edit:
Update will set the identityId and token, however explicit calls made just beforehand may cause it to think no change is being made. Can you try eliminating the setter calls as well?
I want to add username and password to soap header in java by using PasswordText Type and axis2.
Code snippet I use
public static void WSSPasswordAuthentication(org.apache.axis2.client.ServiceClient client, String endPointUrl, String username, String password) throws CSException{
OMFactory omFactory = OMAbstractFactory.getOMFactory();
OMElement omSecurityElement = omFactory.createOMElement(new QName( "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security", "wsse"), null);
OMElement omusertoken = omFactory.createOMElement(new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "UsernameToken","wsse"), null);
OMElement omuserName = omFactory.createOMElement(new QName("", "Username", "wsse"), null);
omuserName.setText(username);
OMElement omPassword = omFactory.createOMElement(new QName("", "Password", "wsse"), null);
omPassword.addAttribute("Type","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText",null );
omPassword.setText(password);
omusertoken.addChild(omuserName);
omusertoken.addChild(omPassword);
omSecurityElement.addChild(omusertoken);
client.addHeader(omSecurityElement);
}
And resultant header :
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsu:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><Username>erapor</Username><Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">erapor</Password></wsu:UsernameToken></wsse:Security>
But
The header I want : <soapenv:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username>erapor</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">erapor</wsse:Password></wsse:UsernameToken></wsse:Security></soapenv:Header>
Otherwise I couldn't use the header
How can I modify?
You can use plain JAXWS if you have an option to resolve this instead of using AXIS2 on the client side. This is generic and easy to add these kind of security headers.
In your JDK 6.0 HOME (This example works only from JDK 6.0 and above)
jdk1.6.0_26\bin\wsimport is an utility available
You can create the stub using the wsimport utility
wsimport -keep -verbose http://localhost:8080/<WebserviceName>/services/<WebserviceName>?wsdl
Create a message handler
MessageHandler.java
package com.secure.client;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class MessageHandler implements SOAPHandler<SOAPMessageContext>{
#Override
public void close(MessageContext arg0) {
// TODO Auto-generated method stub
}
#Override
public Set getHeaders() {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean handleMessage(SOAPMessageContext soapMessageContext) {
try {
boolean outMessageIndicator = (Boolean) soapMessageContext
.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outMessageIndicator) {
SOAPEnvelope envelope = soapMessageContext.getMessage().getSOAPPart().getEnvelope();
SOAPHeader header = envelope.addHeader();
SOAPElement security = header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse");
usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
SOAPElement username = usernameToken.addChildElement("Username", "wsse");
username.addTextNode("wsuser");
SOAPElement password = usernameToken.addChildElement("Password", "wsse");
password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
password.addTextNode("wspwd");
}
} catch (Exception ex) {
throw new WebServiceException(ex);
}
return true;
}
}
Create HeaderHandlerResolver.java
package com.secure.client;
import java.util.ArrayList;
import java.util.List;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
public class HeaderHandlerResolver implements HandlerResolver {
#SuppressWarnings("unchecked")
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
MessageHandler hh = new MessageHandler();
handlerChain.add(hh);
return handlerChain;
}
}
You can create the client code using stub
Client.java
import javax.xml.ws.BindingProvider;
import com.secure.HelloService;
import com.secure.HelloServiceException;
import com.secure.HelloServicePortType;
public class Client {
public static void main(String[] args) {
HelloService service = new HelloService();
service.setHandlerResolver(new HeaderHandlerResolver());
HelloServicePortType port = service.getHelloServiceHttpSoap11Endpoint();
// Use the BindingProvider's context to set the endpoint
BindingProvider bp = (BindingProvider)port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8080/<WebserviceName>/services/<WebserviceName>");
System.out.println(port.getVersion());
try {
System.out.println(port.getHello("Zack"));
} catch (HelloServiceException e) {
e.printStackTrace();
}
}
}