I'm using org.keycloak:keycloak-admin-client:12.0.4. I've been doing some research about how to use the API.
Here are a couple examples:
// ----
// Getting a JWT
// ----
Keycloak keycloak = KeycloakBuilder.builder()
.serverUrl("http://localhost:8180/auth")
.grantType(OAuth2Constants.PASSWORD)
.realm("dev")
.clientId("example-client")
.clientSecret("1169ef64-ea8f-47eb-9e55-74fdda9ee398")
.username("user1")
// raw password
.password("user1Pass")
.resteasyClient(
new ResteasyClientBuilderImpl()
.connectionPoolSize(10).build()
).build();
AccessTokenResponse atr =
keycloak.tokenManager().getAccessToken();
// ----
// Creating a new user
// ----
UserRepresentation user = new UserRepresentation();
user.setEnabled(true);
user.setUsername("tester1");
user.setFirstName("First");
user.setLastName("Last");
user.setEmail("example#email.com");
user.setAttributes(Collections.singletonMap("origin", Arrays.asList("demo")));
RealmResource realmResource = keycloak.realm("dev");
UsersResource usersRessource = realmResource.users();
Response response = usersRessource.create(user);
String userId = CreatedResponseUtil.getCreatedId(response);
CredentialRepresentation passwordCred = new CredentialRepresentation();
passwordCred.setTemporary(false);
passwordCred.setType(CredentialRepresentation.PASSWORD);
// raw password
passwordCred.setValue("test");
UserResource userResource = usersRessource.get(userId);
So in both of these situations, I'm using a String which is the raw password. My question is, should I be hashing passwords before sending them to Keycloak?
It's not that I distrust Keycloak, I'm just curious if Keycloak itself is doing some hashing in its own implementation. I've done some searching on Google, but haven't found any what I'm looking for.
Related
I have a problem for a backend solution developpement. I need someone to guide me.
I'm developping a backend solution with SpringBoot.
My backend should :
Connect to an Active Directory
Use a token system for the security part
Give special access for each request (based on AD group)
After a lot of tests and research, I already have this :
Connect to an Active Directory
For the connection to AD part, I did this :
Inside a class that extends WebSecurityConfigurerAdapter
#Override
public void configure(AuthenticationManagerBuilder auth) {
ActiveDirectoryLdapAuthenticationProvider adProvider
= new ActiveDirectoryLdapAuthenticationProvider("domain.com", "ldap", "ou,dc");
adProvider.setConvertSubErrorCodesToExceptions(true);
adProvider.setUseAuthenticationRequestCredentials(true);
adProvider.setUserDetailsContextMapper(userDetailsContextMapper());
auth.authenticationProvider(adProvider);
}
userDetailsContextMapper() simply maps the info to an user class that contains the username, the lastname and the list memberOf of the user (AD groups).
Using token
I use this method for the token. It works too.
public SignedJWT getToken(String username) {
JWSSigner signer = null;
SecureRandom random = new SecureRandom();
byte[] sharedSecret = new byte[32];
random.nextBytes(sharedSecret);
signer = new MACSigner(sharedSecret);
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
.subject(username)
.issuer("domain")
.expirationTime(new Date(new Date().getTime() + 60 * 1000))
.build();
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
signedJWT.sign(signer);
String serializedToken = signedJWT.serialize();
return signedJWT;
}
Access per request
For the third part I want to give access to a specific request only for a given AD group.
Imagine I have two correctly mapped request :
domain.com/sales/2022/all : Return all the sales values for the year 2022
domain.com/IT/inventory/all: Return all the IT inventory
I want only the people that are from the group IT that can get a result from the IT's request and for the sale's request, only someone who is a member of the groupe sales.
But first of all, I want only people who are authenticated and have a valid token who can call a request.
I searched and tested different solutions on the internet but I did not find anything compatible with my two previous method.
Can you help me ? I'm not specially looking for a solution, a link to a good documentation or some example are enough for me.
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) );
How can I login with MD5 hashed password to openfire?
I'm using smack 4.0.4.
I've tried DIGEST-MD5 registiration but it's not work
SASLAuthentication.registerSASLMechanism("DIGEST-MD5", SASLDigestMD5Mechanism.class);
SASLAuthentication.supportSASLMechanism("DIGEST-MD5");
I'm getting this error :
SASLError using PLAIN: not-authorized
My code looks like this:
config = new ConnectionConfiguration(xmppServerAddress, Integer.parseInt(xmppServerPort));
config.setDebuggerEnabled(true);
config.setReconnectionAllowed(true);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
XMPPTCPConnection connectionTmp = new XMPPTCPConnection(config);
connectionTmp.connect();
connectionTmp.login("username","md5hashedpassword");
I have a similar problem, you could check if your password is in md5.
I have generate a passwords from the userid (long type) as:
#Override
public String generatePassword(long userId) {
String userIdString = String.valueOf(userId);
return MD5util.getMD5(userIdString + StringUtil.getStringAlternateCharacters(userIdString));
}
or find out that your xmpp server (openfire) IP is correctly configured as you wish to login.
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.