I have been looking through the Keycloak documentation but cannot see how to do this. With Java, I'd like to take a valid userid and password and then generate a token. How can I do this?
--EDIT 2018-08-31--
You can use the Authorization Client Java API. Once you have created an AuthzClient object, you can pass the username and password to the AuthzClient#authorization(username, password) or AuthzClient#obtainAccessToken(username, password) method to authenticate the user and get the access token (and/or ID token in the first case):
// create a new instance based on the configuration defined in keycloak-authz.json
AuthzClient authzClient = AuthzClient.create();
// send the authorization request to the server in order to
// obtain an access token granted to the user
AccessTokenResponse response = authzClient.obtainAccessToken("alice", "alice");
On a side note, if possible, you'd rather reuse one of the Keycloak Java Adapters to cover more features, such as other authentication methods (the user is typically redirected to Keycloack WUI where you can enforce very flexible authentication and authorization policies).
Related
I've created webapp (not native) in Azure AD. I have java code (adal4j) that
acquire token using appId/appSecret credentials:
String clientId = "xxxxxxxxxxxxxxxxxxxxxx";
String clientSecret = "yyyyyyyyyyyyyyyyyyyyyy";
String resourceUrl = "https://graph.windows.net";
String authorityUrl = "https://login.microsoftonline.com/zzzzzzzzzzzzzzzz/oauth2/authorize";
ExecutorService executorService = Executors.newFixedThreadPool(4);
Optional<UserInfo> userInfo = Optional.empty();
try {
AuthenticationContext authContext = new AuthenticationContext(authorityUrl, false, executorService);
Future<AuthenticationResult> future = authContext.acquireToken(resourceUrl, new ClientCredential(clientId, clientSecret), null);
AuthenticationResult result = future.get();
}
Now I would like to check if specified user/password combination is in Azure AD and if yes then get First and Last name of this user.
Is it possible to do this usinq acquired token ? How to write such code using adal4j ?
It sounds like what you're really trying to do is sign in a user and get their first/last name. As the comment said, the pattern suggested is not a valid one and would represent a security issue. Additionally, the use for clientId and clientSecret is not exactly for user credentials, but for app credentials. This is used for flows without user interaction for service/api applications, and doesn't sound like what you'll want.
Now, to achieve this you'll be using the OpenID Connect protocol. To simplify what will happen, your app (upon user trying to sign in) will redirect to the Microsoft sign in page (https://login.microsoftonline.com), enter their credentials and fulfill any other authorization requirements, consent to your app, and then redirected back. When they come back, your app will receive an ID Token which can be validated and used to get information about the user that has just sign in. During this time, Azure AD / Microsoft will also set a cookie on the browser so the user will get SSO across their account.
In terms of how to achieve this, I recommend following the ADAL4J Code Sample. This will get your app an ID Token, and also an Access/Refresh token that you can use to call the Microsoft Graph API. This API can also get you information about the user (basic profile info), but also their Office365, Intune, and Windows data.
String userPoolId="testPoolID";
String username= "testuser";
String amazonAWSAccessKey="test access key";
String amazonAWSSecretKey="test secret key";
AdminDeleteUserRequest req = new AdminDeleteUserRequest();
req.setUsername(username);
req.setUserPoolId(userPoolId);
AWSCredentials credentials = new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);
credentialsProvider.getCredentials();
req.setRequestCredentialsProvider(credentialsProvider);
AWSCognitoIdentityProvider provider = new AWSCognitoIdentityProviderClient();
provider.adminDeleteUser(req);
This is the code snippet for deleting a user from cognito User pool. How we can delete a user from cogito without providing credentials using java ?
One way to do this would be to put this code in a lambda & expose it via API Gateway. Create another userpool for admins (its free!) & enable cognito userpool authorizers for your API. Now in your code, show a login screen (use Cognito's built-in UI) ,get the ID tokens and use this ID token while calling your API. This way your code will dynamically get tokens & so no hard-coded credentials.
Another way would be to use Cognito Federated Identities but in this case no lambda + API Gateway is needed. Again, create a userpool for Admins & add this as an Auth Provider in a Cognito Identity Pool. Now, login to the Admin userpool, get an Id token, use this token in the login map for the IdentityPool & get temporary credentials using GetCredentialsForIdentity. Just make sure that the Auth role for the Cognito Identity Pool has appropriate permissions to perform userpool actions.
Sorry its late, might be helpful for others who stumble on this.
If your code is in a lambda you can use the following code
AWSCognitoIdentityProviderClientBuilder.standard()
.withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
.withRegion(region).build();
Note: Check if your lambda execution role is having access to cognito
I have a web application that I deploy using JBoss 5.2. In order for a user to use the application, he/she must authenticate with an LDAP server (using simple authentication) with a username and password. This is all done through setting up the login-config.xml for JBoss and providing a <login-module> with our implementation.
The problem comes in here: After having logged in, I have a scenario that requires the user to provide a username & password when a particular action is performed (which I will also authenticate with the LDAP server). I want to be able to reuse the same mechanism that I use for authenticating the user into the web application.
My form to log in to the application posts to j_security_check so in accordance with this, I was trying to send a request to j_security_check but JBOSS returns a 404. From reading around a bit, I've gathered j_security_check cannot be accessed by any arbitrary request and must be in response to a challenged request to a secured resource.
So then, how can I authenticate the second set of credentials the user has provided with the same LDAP server?
EDIT:
To clarify, the question is how to send the user's credential inputs to the LDAP server for authentication. Grabbing the input from the user, etc. is all done. All that is left is to take this input and send it to the LDAP server and get the response (which is where I am stuck).
If it helps to mention, the login to the web application uses a custom class that extends UsernamePasswordLoginModule.
So, after lots of research, I ended up finding a solution for JBoss environments (which is what I'm using).
Once you capture the user's credentials, you send them to your server via a POST/GET and your server can perform the following to use whatever authentication policy you have configured (in login-config.xml) to verify the credentials:
WebAuthentication webAuthentication = new WebAuthentication();
boolean success = webAuthentication.login(username, password);
To expand on this, I was also able to check the user's role/group via the HttpServletRequest (which is passed into my server-side handler):
boolean userIsInRole = servletRequest.isUserInRole("nameOfGroup")
The spring security documentation explains it
Wanted to add another answer for JBoss 6.2+, where WebAuthentication no longer exists.
I've used the creation of a LoginContext to achieve the same result:
String SECURITY_DOMAIN_NAME = "ssd"; // the security domain's name from standalone.xml
String username = "user";
String password = "password";
LoginContext lc = null;
try {
lc = new LoginContext(SECURITY_DOMAIN_NAME, new UsernamePasswordHandler(username, password.toCharArray()));
lc.login();
// successful login
} catch (LoginException loginException) {
// failed login
}
And the use uf lc.getSubject().getPrincipals() to verify roles.
I am developing a small REST-webservice for non critical data which will mainly be accessed by a smartphone application. For limiting the access of the users to their individual data (the authorization does not need groups or roles), I need to implement some sort of basic authentification.
As the service will be accessed over HTTP, using HTTP-Authentification seems to be no good idea as the username and password will be sent in cleartext on every request and need to be stored on the client device.
Thus, my idea was to implement authentification the following way:
The user logs on using a login method of my webservice passing their username / password
This method checks the validity of the username / password combination (based on a database containing salted and hashed passwords)
If the login is successful, the id of the user (primary key of the database table) is stored in the session as an attribute
In the following requests, this attribute is used to authentificate the user
In code, my login method would look like the following:
User user = this.authentificate(username, password);
HttpSession session = request.getSession(true);
if (user != null)
session.setAttribute("UserId", user.getId());
else
session.invalidate();
Afterwards, I would be able to authentificate the user based on the session:
int userId = (int) request.getSession().getAttribute("UserId");
User currentUser = getUserById(userId);
Can this approach be considered as "secure" (no easy session highjacking possible - as far as I understood https://stackoverflow.com/a/5838191/232175 , the attributes' values won't leave the server)?
Are there any downsides or alternatives?
With regard to storing the user id in the session, I think that is OK, but you have another problem.
First, I would assume that the login method would be over HTTPS, otherwise the username and password would be sent in clear text to the login method and you are right back to the same problem you had before.
Second, if the login method were over HTTPS, then the session cookie would be an HTTPS cookie and all other API calls would also need to be over HTTPS. If subsequent calls were over HTTP, they would get a new session cookie and the user id would be unavailable in that session.
If you really want secure authentication without HTTPS, you would need to use a shared secret signing scheme (e.g. HMAC) or an asymmetric signing system like RSA to have the client sign requests and then validate those signed requests server side.
Right now i'm using java to build rest service, and trying to use spring security to securing my service.
I have a few parameter that server needs to process the service (ex: application ID, username, password, consumer ID) . For username and password, I put in on http header "authorization", encoded with base64. Is there a way to put another parameters above (ex. AppID, consID) into http header?
Some sample of code would help, thanks.
You can put whatever you want in a whatever header you like. You can create custom headers. So you can have a App-Id header where you pass the appId. Alternatively you can pass those as parameters in the URL. That way you'll get rid of the option that some (stupid) proxy trims your headers.
Btw, I would suggest not to send the password, unless you are using https. Generally, I can recommend two similar scenarios:
use OAuth - let the user grant access to the API client via the OAuth dance. The client ends up with a token which it uses on each request.
use a custom, simplified token scheme - login once (with username and password, over https), and send a short-lived token in response. Each subsequent request can be made over an unsecured connection by providing the token, and (optionally) some HMAC of the request parameters, using a consumer secret as a key, so that you can verify the client is legit.