socialService find method implementation - authentication

I'm trying to apply Social Service 2.1.3 to my app (play framework). I have hard time with find method implementation. Right now (in save) method (after user login) i'm putting user Identity obj. to play cache (to avoid overusege of rest api that i'm useing). But it dose not work in the way I wont to.
When user logout from google account my app miss this event, user can still operate and manipulate with data. How can i get to information about current status of user login/logout. I thought about event listener or AuthenticatorStore but cant find any examples how to use it.
best regards
Andrew

SecureSocial can't detect if a user logs out from an external service such as Google or Facebook.
When a user logs into your app SecureSocial will ask the external service to perform authentication. If successful the module will create an Authenticator to track that authenticated session.
The event listener works for actions done against SecureSocial itself, not the external providers.

Related

How to store and use multiple users' keys for third party client

I want to build web app that uses Spotify API. I got case where user has to authenticate with his spotify account, then I recive access and refresh token that is being used in code to authenticate calls to Spotify to perform some actions on user's account.
I have trouble deciding how it should be really done. First thing that came to my mind - store them in Redis for some time, update on refresh and whenever we need to perform some action on any user we get his credentials and do it. Is this proper way? I tough about simply storing them in app memory but I might want to make in serverless.
Did anyone come accross that kind of problem? Do anyone know how to do it 'properly'.

Keycloak - Multi/2FA Factor - OTP - QR Code - Custom Login Screen - Rest API

I have my own Login page where user enters username/password.
This username/password are used to login through Keycloak Rest API.
http://localhost:8080/auth/realms/Demo/protocol/openid-connect/token
input - {username,password,grant_type,client_secret,client_id}
And in response i get access token.
Now i wish to enable Authenticator (Google Authenticator). I have enabled it from backend. Now if user wishes to login thorugh my application, my login page i need to get below details.
1.) Somehow i need to include QR Code that appears on keycloak login page post username/password validation to show on my login screen for the first time login once user enter username/password. So do we have any API which return Keycloak QR code image in response.
2.) Subsequent login i will have OTP field, so need a REST api to pass OTP along with username/password.
Please help with REST API if keycloak has any. Integrating through Javascript.
Similar flow as described in use case 1 here
Just want to use keycloak as a database, doing all operation for me, input will be my screen. I do want redirection of URL's while login in and yet should be standalone deployed.
I've managed to implement this through the rest API of Keycloak. To realize this, you need to extend Keycloak yourself with a SPI. To do this create your own Java project and extend org.keycloak.services.resource.RealmResourceProvider and org.keycloak.services.resource.RealmResourceProviderFactory. You can find more information in the official docs (https://www.keycloak.org/docs/latest/server_development/#_extensions), github examples and other stack overflow posts how to do this.
Once you got this up and running you can implement it like this:
#GET
#Path("your-end-point-to-fetch-the-qr")
#Produces({MediaType.APPLICATION_JSON})
public YourDtoWithSecretAndQr get2FASetup(#PathParam("username") final String username) {
final RealmModel realm = this.session.getContext().getRealm();
final UserModel user = this.session.users().getUserByUsername(username, realm);
final String totpSecret = HmacOTP.generateSecret(20);
final String totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user);
return new YourDtoWithSecretAndQr(totpSecret, totpSecretQrCode);
}
#POST
#Path("your-end-point-to-setup-2fa")
#Consumes("application/json")
public void setup2FA(#PathParam("username") final String username, final YourDtoWithData dto) {
final RealmModel realm = this.session.getContext().getRealm();
final UserModel user = this.session.users().getUserByUsername(username, realm);
final OTPCredentialModel otpCredentialModel = OTPCredentialModel.createFromPolicy(realm, dto.getSecret(), dto.getDeviceName());
CredentialHelper.createOTPCredential(this.session, realm, user, dto.getInitialCode(), otpCredentialModel);
}
The secret received with the GET must be send back with the POST. The initial code is the one from your 2FA app (e.g. Google Authenticator). The QR code is a string which can be displayed in an img with src 'data:image/png;base64,' + qrCodeString;
I know this is an old question, but I've recently been looking at something similar, and so thought it would be potentially valuable to share what I have found for others who may be looking into this and wondered what the possibilities are.
TL;DR
You can only really use the existing Keycloak actions to do this or embed the user account management page found at https://{keycloak server URL}/auth/realms/{realm name}/account in an iframe. That's it, I'm afraid. In my opinion it is currently best to just assign actions directly to accounts or use the Credential Reset emails to assign actions; both of these can be done via the Admin API if desired:
Send Credential Reset email containing assigned actions:
https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_executeactionsemail
Set actions directly on the account (include the actions in the requiredActions portion of the user JSON that you send in the body to the endpoint):
https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_updateuser
Background is that as part of a project that I have been working on we wanted to see if we could have an integrated way for users to set up their initial password and OTP device when a new account has been created for them, since the default method of sending them an email from Keycloak using the "Credential Reset" functionality has the limitations that a) it doesn't provide a link to the application itself unless you override the theme, and if you have multiple instances of the application for different users you have no way of knowing which instance to provide the link for, so may have to end up including a list of them, and b) it often doesn't feel truly native to the application, even with changes to the theme. If you're sensible though, I'd suggest you stop and just use this functionality - please see the TL;DR section above for details.
So, in short there is NO API endpoint for receiving a QR code to set up an OTP device. There are two places, however, where the QR code can be retrieved from - the OTP device setup screen when you log in as a user who has had a "Configure OTP" action assigned to their account, and the user's own account management screen.
The first option of the Configure OTP action screen is a non-starter. It only shows up when you log in, and so by definition the user has to log in to Keycloak via the Keycloak login page in order to trigger the page to be displayed. At this point you're already on a Keycloak page instead of one of your app's pages, and so unless you can get very creative with changes to these Keycloak pages via a custom theme, tapping into this page isn't really an option.
The second option is more interesting, but far from ideal. Every user who has logged in has access to an account management page that can be found at https://{keycloak server URL}/auth/realms/{realm name}/account. This page allows you to do things like change your name, password, etc. and it also allows you to add an OTP device if you don't already have one, or delete any existing OTP devices associated with your account. This OTP device tab of the account management page can be reached directly via https://{keycloak server URL}/auth/realms/{realm name}/account/totp.
As I mentioned, there isn't an API that you can access to view the QR code that shows up on this page. The only way it is accessible is via the GET request to https://{keycloak server URL}/auth/realms/{realm name}/account/totp, which returns the HTML for the page I've already mentioned. Okay great, so can we scrape the QR code programmatically and then put it in our own page on our application? Err, no, not really. You see, whilst a lot of the Keycloak API endpoints rightly allow you to send a bearer token (e.g. access token) in the authorization header to access and endpoint, this page will not accept a bearer token as a means of authentication/authorization. Instead it uses a session cookie that is locked down to the Keycloak URL. This cookie is set when you log in to your application via the Keycloak login page, and so is available to this account management page when you navigate to it, having already logged in, and since the account management page uses the same server and domain name as the original Keycloak login page, it has access to the cookie and can let you in. This cookie cannot be sent by your application to e.g. your own REST API to then programmatically call the account management page and scrape the QR code, because your application doesn't have access to it for good security reasons. This might be something you can change in Keycloak somewhere, but if there is I would strongly recommend against changing it.
So if we can't scrape the page from our own server, can we do something on the front-end? Well, as mentioned, your application doesn't have access to the session cookie but if you make a request (e.g. using fetch or axios) in your front-end JavaScript to the account management page then that request will send the cookie along with it, so that could work right? Umm, well actually you will get hit with an error message in this scenario due to CORS. CORS is Cross-Origin-Resource-Sharing and in order to allow the Keycloak page to be accessed then you would have to open up the settings on the server to allow it to be accessed from your website's address. I've seen some articles that look at how you can open up your CORS settings on Keycloak if you wish but I'd be very nervous about doing this. I don't know enough about the internals of Keycloak and how it operates to comment on how much of a security risk this is, but I certainly wouldn't recommend it. There some information here (Keycloak angular No 'Access-Control-Allow-Origin' header is present) on changing the "Web Origins" setting of your application's Keycloak client, but this opens up your application to some serious potential abuse. There is also the MAJOR issue that even if you scraped the QR code, the device isn't actually added to the user's account (even though it appears in the authenticator app) until you enter a code into the page that the QR code is on and click Save. Since there isn't an API endpoint that you can use to complete this operation, I therefore don't think that this option is viable either. I've tried out whether or not you can use the token retrieval endpoint at https://{keycloak server URL}/auth/realms/{realm name}/protocol/openid-connect/token to see if making a request with your username/password/otp code will somehow "register" your device and complete the process, but although you can get a token this way, and it doesn't complain about the otp code, it doesn't actually take any notice of the code because as far as it's concerned the user's account doesn't have a device registered with it. So we have to use the form on the account management page in order to complete this registration process.
So the final way of possibly doing this is.... an iframe. Sorry, yeah it's rubbish but that's all your left with. You can have the iframe point at your account management page, and because the user is logged in then they will be able to see the contents from your application's page. You can use relative positioning, fixed width and height and remove scroll bars to ensure that you ONLY show the QR code and the fields for the one time code, device name, and the Save/Cancel buttons. This, sadly, seems to be the only option at the moment, and due to how nasty and unreliable iframes can be in general - they certainly don't feel native to your application, and you'll need to override your Keycloak theme to get the page in question to look more like your app - I'd recommend steering clear of this and using the standard approach of using Keycloak actions and the Admin API instead.
If you've made it this far, congratulations, you win at Stack Overflow :-)

Adding arbitrary objects in the OpenFire Session

We have an existing OAuth2 based website. Our plan is to use a web based (XMPP over websockets) chat system.
now this chat system will be available once the user logs in. What we actually do not want is to login twice, once for the web site and once for the chat system.
So I figured how to trick it with my own auth provider and a custom username/password.
So basically the question is how do I have an object that I want to travel along with the user chat session so that I can provide out of band processing.
Does the session management allow this?
In a similar use-case, there I need to persist and store various pieces of information about a user, in Openfire, so that external calls and look-ups are not necessary during later, custom logic in an Openfire plugin. It is possible to add any number of custom properties to an openfire user, via REST, or other APIs.
Then, those custom properties can be retrieved as needed, without external calls.
create user api
Then, if using Internal APIs, you get
Get the session's username or address (JID)
call UserManager's getUser on the username or JID to get the User object
call User's getPropertyValue to get a specific property or getProperties to retrieve all custom user properties

Spring. Java. Log in and activation email

I have a "chicken egg" problem.
In application I use UserDetailsService to get User (we don't store user information in our DB, we use third party service to actually get all information).
Recently we've added account activation feature. After registration, we send an activation email to a user and if he clicks on it, we mark the User as ACTIVE and redirects him to log in page. User can login only if he has ACTIVE status. The problem is: we'll start charging user from the date he activates his account even if he never logs in. How can I (maybe using spring security) make those processes (activation and login) almost simultaneous? We don't want to charge user if he just activates his account, we want to charge him only if he has logged in (after activation). So can I actually do it somehow "user clicks activation link, login and then his status is changed to ACTIVE (but he can login only if he is ACTIVE)".
Sorry if my problem description isn't clear enough
I'll appreciate any feedback.
Thanks!
If I understood your requirements correctly, you'll need two different entry points (login pages) to your application:
One for activation (first login) for users not yet activated.
Another "normal" one for active users.
The problem is that the authentication logic would need to be context sensitive and be aware of which of the above pages initated the authentication. However the framework was not designed for such uncommon use-cases, so the authentication provider has no knowledge about the URL from which the login-form were actually sent.
What you need to solve is to somehow relay contextual information to an authentication provider that processes the auth request according to that information (i.e. authenticate only non-active users logging in from url1, and authenticate only active users logging in from url2). There could be hundreds of different ways to achieve this, one possible solution is to put two different authenentication filters in place that intercept auth requests sent to the two different urls. Details outlined below:
Create your own custom versions of the existing WebAuthenticationDetailsSource and WebAuthenticationDetails (preferably by subclassing the latter) that stores and exposes the URI of the authentication request. (That will be the contextual information based on which the auth provider can implement its conditional logic.)
Configure and insert two different instances of the UsernamePasswordAuthenticationFilter in the filter chain. Set their filterProcessesUrl attribute to /j_spring_security_check_active_user and /j_spring_security_check_nonactive_user respectively, plus inject the above created custom AuthenticationDetailsSource in both of them.
Override DaoAuthenticationProvider.additionalAuthenticationChecks() in a subclass in the following way:
Retrieve the URI stored in the above created WebAuthenticationDetails object (it's accessible via authentication.getDetails())
Assert that the user is active/non-active according to the URI, and throw an AccountStatusException if the asserion fails.
Don't forget to delegate to the superclass if the assertion succeeds.
Create the two different login pages mentioned at the beginning of the post, making sure that the login forms post credentials to their respective URL (/j_spring_security_check_nonactive_user vs. /j_spring_security_check_active_user).

GITkit "Account Chooser" Questions

Has anyone successfully implemented the Google Identity Toolkit, an implementation of an Account Chooser. I followed the initial steps here, but I still have a few questions, as I don't quite know how to handle the entire data flow. I'm using Clojure / Compojure in the back-end:
http://havethunk.wordpress.com/2011/08/10/google-identity-toolkit-asp-net-mvc3/
http://code.google.com/apis/identitytoolkit/v1/acguide.html
A) don't quite understand how ID Provider authentication, fits into my data model
when implementing the callbackURL, what data should I expect, and
how's that session state managed by GITkit (and all Account Choosers)
B) Is there a way to set this up the 'callbackURL' for development.
the identity provider would need a URL that it can redirect back to
C) How can the GITkit / Account Chooser workflow let my users register an account that's native to my app?
Thanks in advance
The questions aren't entirely clear, but I've done an implementation of GITkit in ruby and can give you some pointers.
A) The callback URL is what handles the assertion from the identity providers. Rightnow GITKit only does OpenID, so the URL will contain an OpenID response either in the query parameters or as the POST body. You'll need to do a few things:
1) Call verifyAssertion in the gitkit API and pass the params/post body. This will return a JSON response that contains the user details (assuming assertion is valid). There are some other checks you should do as well
2) Decide what to do with the assertion. If it is an existing user, most likely you'll just establish a session and save the user ID. If it's a new user, you can either create a new account and start a session immediately, or defer that and redirect them to a signup page.
3) Render HTML/JS to notify the widget. There are different status codes and data you can return that changes the flow.
GITKit itself doesn't really manage session state, that's up to your app. Some of the reference implementations have code to help, but it's not part of the API. The widget does have some state that you can control with JS (add account, show as logged in, etc) and uses local storage in the browser.
The docs give some details and example code for how this should be implemented.
B) Of course. The URL is just configured in the javascript widget when you call setConfig() It can be set to localhost or any staging server for development. So long as your browser can reach it you're OK.
C) By "native", I assume you mean where they're signing up with just a username/password instead of using an IDP. If so, the user just has to enter their email address when logging in. If that email address matches a known IDP it'll attempt to authenticate with OpenID, otherwise if it's a new user it'll redirect to whatever signup page you configured in the widget. That signup page would just ask the user to create a password like you normally would. You should also return whether or not accounts are 'legacy' (password) accounts in the userStatus checks.
Hope that helps.
For anyone's future reference. I was able to resolve the issue. You can follow this thread of how's it's done in Clojure.
I got it working with Ring/Compojure, and another fellow showed me his solution in Webnoir.
HTH