I'd like to have from an admin user the context of the current loggin user.
For that, I use the admin token to have the current one with the function impersonateUser() because I don't have the password of the user.
I have the following error when I call the impersonateUser() on the Authentication object :
javax.xml.ws.soap.SOAPFaultException: OTDS username and password are required.
Here my example :
URL authLocation = new URL("http://localhost:8080/les-services/services/Authentication?wsdl");
String aToken = WebServiceUtil.getAuthenticationToken(authLocation, username, password);//admin token
OTAuthentication fOTAuth = new OTAuthentication();
fOTAuth.setAuthenticationToken(aToken);
com.opentext.livelink.service.core.Authentication auth = webServiceUtil.getAuthenticationService(authLocation);
String token = auth.impersonateUser(newUser);
fOTAuth.setAuthenticationToken(token);
I also found a class ImpersonateUser but I don't know how to use it :
ImpersonateUser impUser = new ImpersonateUser();
impUser.setUserName(newUser);
Do you have any advice ?
Thanks !
Here are the docs for the ImpersonateUser() method.
Related
We've migrated from adal4j to msal4j in our java web applications.
All works well but the big difference is that when the user is already logged (maybe in other applications but same browser session) we always see the "select user" page and the user is not logged automatically and redirected to redirect uri as before with adal4j.
This is how we redirect to autentication page:
private static void redirectToAuthorizationEndpoint(IdentityContextAdapter contextAdapter) throws IOException {
final IdentityContextData context = contextAdapter.getContext();
final String state = UUID.randomUUID().toString();
final String nonce = UUID.randomUUID().toString();
context.setStateAndNonce(state, nonce);
contextAdapter.setContext(context);
final ConfidentialClientApplication client = getConfidentialClientInstance();
AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters
.builder(props.getProperty("aad.redirectURI"), Collections.singleton(props.getProperty("aad.scopes"))).responseMode(ResponseMode.QUERY)
.prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build();
final String authorizeUrl = client.getAuthorizationRequestUrl(parameters).toString();
contextAdapter.redirectUser(authorizeUrl);
}
I've tried to remove .prompt(Prompt.SELECT_ACCOUNT)
but I receive an error
Any ideas?
• You might be getting the option for selecting the user account after switching to MSAL4J in your browser even after the SSO is enabled because either clearing the token cache is enabled in your code or MsalInteractionRequiredException option is thrown and specified accordingly due to which the application asks for a token interactively.
Thus, please check which accounts information is stored in the cache as below: -
ConfidentialClientApplication pca = new ConfidentialClientApplication.Builder(
labResponse.getAppId()).
authority(TestConstants.ORGANIZATIONS_AUTHORITY).
build();
Set<IAccount> accounts = pca.getAccounts().join(); ’
Then, from the above information, if you want to remove the accounts whose prompts you don’t want to see during the user account selection such that the default account should get selected and signed in automatically, execute the below code by modifying the required information: -
Set<IAccount> accounts = pca.getAccounts().join();
IAccount accountToBeRemoved = accounts.stream().filter(
x -> x.username().equalsIgnoreCase(
UPN_OF_USER_TO_BE_REMOVED)).findFirst().orElse(null);
pca.removeAccount(accountToBeRemoved).join();
• And for the MsalInteractiveRequiredException class in the code, kindly refer to the below official documentation link for the AcquireTokenSilently and other reasons responsible for the behaviour. Also, refer to the sample code given below for your reference regarding the same: -
https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-error-handling-java#msalinteractionrequiredexception
IAuthenticationResult result;
try {
ConfidentialClientApplication application =
ConfidentialClientApplication
.builder("clientId")
.b2cAuthority("authority")
.build();
SilentParameters parameters = SilentParameters
.builder(Collections.singleton("scope"))
.build();
result = application.acquireTokenSilently(parameters).join();
}
catch (Exception ex){
if(ex instanceof MsalInteractionRequiredException){
// AcquireToken by either AuthorizationCodeParameters or DeviceCodeParameters
} else{
// Log and handle exception accordingly
}
}
I'm retrieving token from another system using credentials provided by customer. After the token is retrieved I'm creating a UsernamePasswordAuthenticationToken and put it into SecurityContextHolder.
I would like to store the token as well because I'll need it to perform the API calls. Where do I put the token? I don't like the idea of putting the token to the password property of the UsernamePasswordAuthenticationToken.
You can find the code below:
override fun authenticate(authentication: Authentication?): Authentication {
authentication?.let {
val email = authentication.name
val password = authentication.credentials.toString()
val token = authenticationSource.getAuth(email, password) // I want to store it somewhere!
return UsernamePasswordAuthenticationToken(email, password, listOf(SimpleGrantedAuthority("USER")))
}
throw AuthenticationServiceException("Authentication object is equal null")
}
In order to solve this problem I've provided my own Principal implementation:
data class UserInfo(val email: String, val token: String) : Principal {
override fun getName(): String = email
}
and then passed the instance of UserInfo to the UsernamePasswordAuthenticationToken constructor :
UsernamePasswordAuthenticationToken(UserInfo(email, token), password, listOf(SimpleGrantedAuthority("USER")))
And if you need this token you will be able to retrieve it from the SecurityContext the with a simple line of code:
(SecurityContextHolder.getContext().authentication.principal as UserInfo).token
I have recently started playing with the Bing Ads api for managing my ads and campaigns and I am having problem in authenticating user (not oauth authentication).
I authenticated my user using oauth by the following
private String devToken = "ZZZZZ";
private String clientId = "AAA0BBB-XXXX-AAAAA";
protected static String UserName = "a.v#h.c";
protected static String Password = "********";
// To get the initial access and refresh tokens you must call requestAccessAndRefreshTokens with the authorization redirection URL.
OAuthTokens tokens = oAuthDesktopMobileAuthCodeGrant.requestAccessAndRefreshTokens(url);
System.out.println("Access token: " + tokens.getAccessToken());
System.out.println("Refresh token: " + tokens.getRefreshToken());
authorizationData = new AuthorizationData();
authorizationData.setDeveloperToken(getDevToken());
authorizationData.setAuthentication(oAuthDesktopMobileAuthCodeGrant);
This authenticates my user just fine since I can use the ICustomerManagementService.class just fine for accounts related information
customerServiceClient = new ServiceClient<>(authorizationData, ICustomerManagementService.class);
ArrayOfAccount accounts = searchAccountsByUserId(user.getId());
The above works perfectly. But when I try to do the same with ICampaignManagementService.class like below
campaignServiceClient = new ServiceClient<>(authorizationData, ICampaignManagementService.class);
GetAdsByAdGroupIdRequest cReq = new GetAdsByAdGroupIdRequest();
cReq.setAdGroupId(1234567890L);
campaignServiceClient.getService().getAdsByAdGroupId(cReq);
I get error code 106 saying that the user is not authorized.
The user does not represent a authorized developer.
106
Any help in this regard ?
Please try to set the CustomerId and CustomerAccountId header elements (CustomerId and AccountId of AuthorizationData). These headers are not available with the Customer Management service, but are applicable for Campaign Management service. If that does not resolve the issue please feel free to send the SOAP request + response to support for investigation. I hope this helps!
I'm a beginner with Apache Shiro. I've been following the docs and lots of other tutorials, blogs etc. but I just can't get the authentication to work. When I attempt to login with a valid username and password, I always get an InvalidCredentialsException thrown. I'm using DynamoDB as a custom realm for storing user credentials, but I really don't think that matters. It's obviously the way that I'm storing and/or doing the credential matching that's not correct. Here's my setup:
Shiro.ini:
[main]
myRealm = com.enki.closing.users.DynamoDBRealm
credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
credentialsMatcher.storedCredentialsHexEncoded = false
credentialsMatcher.hashIterations = 1024
myRealm.credentialsMatcher = $credentialsMatcher
Create user account:
String password = ...
ByteSource passwordSalt = new SecureRandomNumberGenerator().nextBytes();
String hashedPasswordBase64 = new Sha256Hash(password, passwordSalt, 1024).toBase64();
// store the hashedPassword and salt in DynamoDB...
// I've tried storing the salt with and without base64 encoding.
The password and salt are stored fine in DynamoDB, the values look alright. Here's the custom realm for authentication:
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken userPass = (UsernamePasswordToken) token;
String username = userPass.getUsername();
...
// pull the matching password and salt out of DynamoDB, no problems...
ByteSource passwordSalt = ByteSource.Util.bytes( storedPasswordSalt );
return new SimpleAuthenticationInfo(username, passwordHash, passwordSalt, getName());
}
This is all pretty much what the docs are telling me to do, but there's something not right. When I try the login, it get InvalidCredentialsException.
I figured out how to get it working. I had to change this (in my custom realm impl):
ByteSource passwordSalt = ByteSource.Util.bytes( storedPasswordSalt );
to this:
ByteSource passwordSalt = ByteSource.Util.bytes(
Base64.decode( storedPasswordSalt) );
I get the error
com.google.gdata.util.AuthenticationException: Unknown authorization header
at com.google.gdata.client.http.HttpGDataRequest.handleErrorResponse(HttpGDataRequest.java:600) ~[gdata-core-1.0.jar:na]
at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:563) ~[gdata-core-1.0.jar:na]
at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:552) ~[gdata-core-1.0.jar:na]
at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:530) ~[gdata-core-1.0.jar:na]
at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:535) ~[gdata-core-1.0.jar:na]
when trying to access the Google Calendar data via their API.
Here is what happens before that error.
1) I authenticate with Google:
final AccessTokenResponse response =
new GoogleAuthorizationCodeGrant(httpTransport,
jsonFactory,
clientId, clientSecret, authorizationCode,
redirectUrl).execute();
final GoogleAccessProtectedResource accessProtectedResource =
new GoogleAccessProtectedResource(
response.accessToken, httpTransport, jsonFactory,
clientId, clientSecret,
response.refreshToken);
LOGGER.debug("response.accessToken: {}", response.accessToken);
this.oauthAccessToken = response.accessToken;
...
2) I read some data via the tasks API:
this.service =
new Tasks(httpTransport, accessProtectedResource,
jsonFactory);
this.service.setApplicationName(this.applicationName);
This seems to work.
3) Then I try to read data from the Google Calendar API:
final OAuthHmacSha1Signer signer = new OAuthHmacSha1Signer();
final GoogleOAuthParameters oauth = new GoogleOAuthParameters ();
oauth.setOAuthConsumerKey("myapp.com");
oauth.setOAuthConsumerSecret(CLIENT_SECRET); // Client secret from "Google API access" page, "Client secret" entry
oauth.setOAuthToken(this.oauthAccessToken); // Access token from step 1
oauth.setOAuthTokenSecret(aAuthorizationCode);
// aAuthorizationCode is taken from the callback URL.
// For http://myapp.com/oauth2callback?code=4/uy8Arb4bhRPwWYSr3QwKPt9lIZkt
// aAuthorizationCode is equal to "4/uy8Arb4bhRPwWYSr3QwKPt9lIZkt" (without quotes)
oauth.setScope(SCOPE_CALENDAR); // https://www.google.com/calendar/feeds/
final CalendarService calendarService =
new CalendarService(APPLICATION_NAME);
calendarService
.setOAuthCredentials(oauth, signer);
LOGGER.debug("calendarService: {}", calendarService);
final URL feedUrl =
new URL(
"http://www.google.com/calendar/feeds/default/allcalendars/full");
final CalendarFeed resultFeed =
calendarService.getFeed(feedUrl, CalendarFeed.class);
At the last line (calendarService.getFeed...) the aforementioned exception occurs.
I have following questions:
1) Is my call
oauth.setOAuthConsumerKey
correct?
I. e. is the "consumer key" equal to "Product name" in the Google API console, or to "Client ID" field (value is something like 42912397129473.apps.googleusercontent.com)
2) Is the setOAuthTokenSecret correct? I. e. is it the code that I get, when Google redirects the user back to my app?
3) If questions 2 and 3 were answered with yes, what else can be the cause of my problem?
Thanks
Dmitri
P. S.: Previously, I could access Google calendar with simple access (i. e. with Google user name and password). However, this is not an option now because users of my app will not want to give away their Google password.
Finally, I solved my problem by following the example at
http://code.google.com/p/gdata-java-client/source/browse/trunk/java/sample/oauth/OAuthExample.java
My advice to all future victims^W users of OAuth: Pay attention to the smallest details in the OAuth tutorials. The OAuth devil lies in details.