I am looking to build a stand-alone ExactTarget SOAP client using CXF.
I was able to create a client using Glassfish Metro, but due to future support considerations we would like to use CXF. I found an old example and associated project, but it is too old to be useful.
Currently I am trying to understand how can I set a handler on the stub/port object and to pass dynamic username and password to it. By dynamic I mean: the app gets username and password from the user at the time of running. Here is the code that I currently have for the Metro implementation:
PartnerAPI service = new PartnerAPI();
Soap stub = service.getSoap();
Map<String, Object> outProperties = new HashMap<String, Object>();
Map ctx = ((BindingProvider) stub).getRequestContext();
requestContext.put(BindingProvider.USERNAME_PROPERTY, user);
requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);
List<Handler> chain = new ArrayList<Handler>();
chain.add(new SecurityHandler());
((BindingProvider) stub).getBinding().setHandlerChain(chain);
I am trying to reuse the first 4-6 lines for the CXF implementation, but I cannot use the handlers I have since they depend on com.sun.xml.wss.XWSSProcessor.
Here is code that does everything:
private static Soap createApiStub() {
PartnerAPI service = new PartnerAPI();
Soap stub = service.getSoap();
Client client = org.apache.cxf.frontend.ClientProxy.getClient(stub);
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, username);
outProps.put(WSHandlerConstants.PASSWORD_TYPE,WSConstants.PW_TEXT);
// Automatically adds a Base64 encoded message nonce and a created timestamp
outProps.put(WSHandlerConstants.ADD_UT_ELEMENTS,WSConstants.NONCE_LN + " " + WSConstants.CREATED_LN);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new ClientPasswordCallback(username, password));
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
client.getOutInterceptors().add(wssOut);
//Enable GZip compression
Map<String, java.util.List<String>> httpHeaders = new HashMap<String, java.util.List<String>>();
httpHeaders.put("Content-Encoding",Collections.singletonList("gzip"));
httpHeaders.put("Accept-Encoding",Collections.singletonList("gzip"));
Map<String, Object> reqContext = client.getRequestContext();
reqContext.put(MessageContext.HTTP_REQUEST_HEADERS,httpHeaders);
return stub;
}
And here is handler implementation:
public class ClientPasswordCallback implements CallbackHandler {
private String username;
private String password;
public ClientPasswordCallback(String username, String password) {
this.username = username;
this.password = password;
}
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (Callback callback: callbacks){
if (callback instanceof WSPasswordCallback){
WSPasswordCallback pc = (WSPasswordCallback) callback;
if (username.equals(pc.getIdentifier())) {
pc.setPassword(password);
}
} else if (callback instanceof NameCallback){
throw new UnsupportedCallbackException(callback);
} else {
throw new UnsupportedCallbackException(callback);
}
}
}
}
This answer helped me to pass the password dynamiclly.
Related
I am trying to create a login token for a user. Let's call that user "manager". There are already existing tokens for different roles. The manager role is a role such that the manager can also be an agent. Thus, a manager should be able to login on two different platforms - Mobile and Web and the manager should not be logged out from either of the platforms.
Here is what the profile service looks like.
public class ProfileService {
private String baseUrl;
private ObjectMapper objectMapper;
public ProfileService(String baseUrl) {
this.baseUrl = baseUrl;
objectMapper = new ObjectMapper();
}
public ProfileDTO fetchUserProfile(String profileId){
Client client = ClientBuilder.newClient();
log.info("This is the base url {}", baseUrl);
Map response = client.target(baseUrl + "/api/v1/users/" + profileId).request().get(Map.class);
Object data = response.get("data");
Map dataMap = this.objectMapper.convertValue(data, Map.class);
Map roleGroup = this.objectMapper.convertValue(dataMap.get("roleGroup"), Map.class);
List roleObjs = this.objectMapper.convertValue(dataMap.get("roles"), List.class);
String userType = dataMap.get("userType").toString();
String roleGroupName = (Objects.isNull(roleGroup)) ? userType : roleGroup.get("name").toString();
List<String> roles = new ArrayList<>();
if (Objects.nonNull(roleObjs)) {
for (Object entry : roleObjs) {
Map role = this.objectMapper.convertValue(entry, Map.class);
roles.add(role.get("name").toString().toUpperCase(Locale.ROOT));
}
}
return new ProfileDTO(dataMap.get("id").toString(), dataMap.get("email").toString(),
dataMap.get("firstName").toString(), roleGroupName, userType,
roles, (Boolean) dataMap.get("enabled"), (Boolean) dataMap.get("verified"));
}
}
Here is the existing service that is not giving me the desired results.
private void verify(ProfileDTO profile, Types.Platform platform) throws AuthenticationException {
if (!profile.isEnabled() || profile.getUserType() == null) {
throw new AuthenticationException("Unauthorized!");
}
switch (platform) {
case WEB:
if(!profile.getUserType().equalsIgnoreCase(Constants.STAFF_ROLE)){
throw new AuthenticationException("Unauthorized web platform user");
}
return;
case MOBILE:
if (!profile.getUserType().equalsIgnoreCase(Constants.AGENT_ROLE)){
throw new AuthenticationException("Unauthorized mobile platform user");
}
return;
case AGGREGATOR:
if(!profile.getRoles().add("AGGREGATOR_ROLE")){
throw new AuthenticationException("Unauthorized aggregator");
}
default:
throw new AuthenticationException("Unauthorized! Unknown platform");
}
}
private String generateToken(ClPrincipal principal) throws JoseException {
final JwtClaims claims = new JwtClaims();
claims.setSubject(principal.getProfileId());
claims.setStringClaim(Constants.USERNAME, principal.getUsername());
claims.setStringClaim(Constants.FIRST_NAME, principal.getFirstname());
claims.setStringClaim(Constants.LAST_NAME, principal.getLastname());
claims.setStringClaim(Constants.ROLE_GROUP, principal.getRoleGroup());
claims.setStringListClaim(Constants.ROLES, principal.getRoles());
claims.setExpirationTimeMinutesInTheFuture(oAuthConfig.getTokenTTL() / 60);
claims.setJwtId(UUID.randomUUID().toString())
What do I do to get the desired result I stated earlier. I keep getting the default message for the switch case ("Unauthorized! Unknown platform")
I am trying how to add a steam logging to my java application .I have try out few OpenID libraries in http://openid.net/developers/libraries, And this is for JOpenID ,
Eg - >
OpenIdManager manager = new OpenIdManager();
manager.setTimeOut(10000);
Endpoint endpoint = manager.lookupEndpoint("http://steamcommunity.com/openid");
System.out.println(endpoint);
Association association = manager.lookupAssociation(endpoint);
System.out.println(association);
String url = manager.getAuthenticationUrl(endpoint, association);
System.out.println("Copy the authentication URL in browser:\n" + url);
System.out.println("After successfully sign on in browser, enter the URL of address bar in browser:");
String ret = url;
HttpServletRequest request = createRequest(ret);
Authentication authentication = manager.getAuthentication(request, association.getRawMacKey(), endpoint.getAlias());
System.out.println(authentication);
Because i am not trying this for web app and I Dont have a callback-URL to use , i have use "easymock"
public HttpServletRequest createRequest(String url) throws UnsupportedEncodingException {
int pos = url.indexOf('?');
if (pos==(-1))
throw new IllegalArgumentException("Bad url.");
String query = url.substring(pos + 1);
String[] params = query.split("[\\&]+");
final Map<String, String> map = new HashMap<String, String>();
for (String param : params) {
pos = param.indexOf('=');
if (pos==(-1))
throw new IllegalArgumentException("Bad url.");
String key = param.substring(0, pos);
String value = param.substring(pos + 1);
map.put(key, URLDecoder.decode(value, "UTF-8"));
}
return (HttpServletRequest) Proxy.newProxyInstance(
Main.class.getClassLoader(),
new Class[] { HttpServletRequest.class },
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getParameter"))
return map.get((String)args[0]);
throw new UnsupportedOperationException(method.getName());
}
}
);
}
But I am getting a error saying ,
java.lang.IllegalArgumentException: interface javax.servlet.http.HttpServletRequest is not visible from class loader
at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:487)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:722)
and i have ALSO try as the code like in
https://gist.github.com/FernFerret/7692878 too (for Openid4java and spark) but got error when creating Route like in link saying there is no 'Route(String)'
get(new Route("/") {
So how can i Make OpenID authentication with out a Redirect URL ?
Can any one can guide me for a java OpenID Authentication for Steam using "any" OpenID code ?
I just need That returned value( like-> http//steamcommunity.com/openid/id/76561197960435530") informed in
http://steamcommunity.com/dev/
Which is the only value that returns .
Many Thanks For Any inputs !!
I'm using socialauth to handle oauth authentication. Also I have basic login&password authentication(not implemented. but service method exists).
public Map<String, String> oauthAuthentication(String source, String callback) throws Exception {
Map<String, String> map = new HashMap<>();
SocialAuthConfig config = new SocialAuthConfig();
config.load("oauth_consumer.properties");
SocialAuthManager socialAuthManager = new SocialAuthManager();
socialAuthManager.setSocialAuthConfig(config);
String url = socialAuthManager.getAuthenticationUrl(source, callback);
map.put("url", url);
map.put("token", socialAuthManager.getCurrentAuthProvider().getAccessGrant().getKey());
return map;
}
public String loginPasswordAuthentication(String username, String password) {
return null;
}
But how to add spring security here? What should I keep and where? What authentication information I should keep? I have context for it and it works fine (intercept request and redirect to login page).
I am trying to invoke a webservice method which takes 2 input parameters and also needs a cookie to authenticate.
PostMethod method = new PostMethod("webservice EP URL");
NameValuePair code = new NameValuePair("Code", "");
NameValuePair revision = new NameValuePair("Rev", "Latest");
NameValuePair targetUri = new NameValuePair("TARGET", "GetObject");
method.setRequestBody(new NameValuePair[] { code, revision,targetUri});
int statusNew = client.executeMethod(method);
I dont know how to achieve it. Above code is what i am doing currently.
Most probably you are dealing with RESTful web services (Just my guess as you are passing parameters as http form params). Here is how to pass cookies
method.setRequestHeader("Cookie", "special-cookie=value");
Here just change "special-cookie=value" to your specific cookie that you are trying to pass.
EDIT: Adding cookie to SOAP request:
The quickest way to do is as follows
(Assuming that the call object you are using is an instance of org.apache.axis.client.Call)
call.setProperty(
org.apache.axis.client.Call.SESSION_MAINTAIN_PROPERTY,
new Boolean(true));
call.setProperty(
org.apache.axis.transport.http.HTTPConstants.HEADER_COOKIE2,
"\r\nCookieName=" + "CookieValue");
Please check "Use a SOAPAction HTTP Header" topic on this link.
Using the SOAP Handler, we can pass the headers in the request and it will do the job.
GetObject_Service_Impl impl = new GetObject_Service_Impl();
// Get Iterator for all service ports
Iterator iter = impl.getPorts();
// Now create a new List of HandlerInfo objects - only one really.
// Our client handler
List handlerChain = new ArrayList();
handlerChain.add(new HandlerInfo(SoapHandler.class, null, null));
// Get Handler Registry
HandlerRegistry registry = impl.getHandlerRegistry();
// Register each port with the handler
while (iter.hasNext())
registry.setHandlerChain((QName) iter.next(), handlerChain);
And Write a new class say SoapHandler.java as below
public class SoapHandler extends GenericHandler {
HandlerInfo hi;
public void init(HandlerInfo info) {
hi = info;
}
public QName[] getHeaders() {
return hi.getHeaders();
}
public boolean handleResponse(MessageContext context) {
return true;
}
/**
* This method is use to add custom headers to existing SAOP request
*/
public boolean handleRequest(MessageContext context) {
System.out.println("response");
try {
SOAPMessageContext smc = (SOAPMessageContext) context;
SOAPMessage message = smc.getMessage();
MimeHeaders hd = message.getMimeHeaders();
hd.addHeader("Authorization", "Basic some credentials");
} catch (Exception e) {
throw new JAXRPCException(e);
}
return true;
}
}
And thats it.....its ready to go.
I'm trying to create a Web Service Client with Metro that uses WS-Security.
I have used Axis2, and to specify the username/password in an Axis2 client, I do:
org.apache.axis2.client.ServiceClient sc = stub._getServiceClient();
org.apache.axis2.client.Options options = sc.getOptions();
options.setUserName("USERNAME");
options.setPassword("PASSWORD");
How do I provide a username/password in a Metro client?
If you want to auth using basic http headers:
#WebEndpoint(name = "WSHttpBinding_ICustomerService")
public ICustomerService getWSHttpBindingICustomerService() {
WebServiceFeature wsAddressing = new AddressingFeature(true);
ICustomerService service =
super.getPort(new QName("http://xmlns.example.com/services/Customer",
"WSHttpBinding_ICustomerService"), ICustomerService.class,
wsAddressing);
Map<String, Object> context = ((BindingProvider)service).getRequestContext();
Map<String, List<String>> headers = new HashMap<String, List<String>>();
headers.put("Username", Collections.singletonList("yourusername"));
headers.put("Password", Collections.singletonList("yourpassword"));
return service;
}
If the service uses NTLM (Windows authentication) (explanation here):
#WebEndpoint(name = "WSHttpBinding_ICustomerService")
public ICustomerService getWSHttpBindingICustomerService() {
WebServiceFeature wsAddressing = new AddressingFeature(true);
ICustomerService service =
super.getPort(new QName("http://xmlns.example.com/services/Customer",
"WSHttpBinding_ICustomerService"), ICustomerService.class,
wsAddressing);
NtlmAuthenticator auth = new NtlmAuthenticator(username, password);
Authenticator.setDefault(auth);
return service;
}
Haven't used this myself, but seen other use it:
#WebEndpoint(name = "WSHttpBinding_ICustomerService")
public ICustomerService getWSHttpBindingICustomerService() {
WebServiceFeature wsAddressing = new AddressingFeature(true);
ICustomerService service =
super.getPort(new QName("http://xmlns.example.com/services/Customer",
"WSHttpBinding_ICustomerService"), ICustomerService.class,
wsAddressing);
Map<String, Object> context = ((BindingProvider)service).getRequestContext();
context.put(BindingProvider.USERNAME_PROPERTY, "yourusername");
context.put(BindingProvider.PASSWORD_PROPERTY, "yourpassword");
return service;
}