Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Manage redirections to Vaadin App
first of all, I have to apologize for my bad english. I hope I can explain my concern nevertheless understandably.
I am working on a Vaadin app which uses Wordpress services - static HTML-Pages, Blog and - very important - User administration. Most services are available over REST-Request. My problem is that the user login has to be done at wordpress, since for the blog use an exclusive oauth registration is not sufficient for Wordpress.
I use an oauth-plugin in wordpress, which supports the login process. For this, it is necessary to call a specific REST request to wordpress. The oauth-plugin checks, if a login already exists for the session. If not, wordpress prints out its login page. This HTML-Page I display in a Vaadin browser component.
After logging on, wordpress calls a callback URL with information needed for another REST request to wordpress. And here is my problem: I can not catch this callback call intercept and process.
I guess by this external call a new Vaadin session is started, but I'm not sure.
Does anyone have an idea how to manage this callback mechanism in Vaadin?
Hi Bernhard, you're right: that external call most probably starts a new Vaadin session since it naturally is missing necessary cookes/jsessionid query parameters which identify the actual session.
I'm guessing that once you receive a call to this callback URL, you would like to hide the browser component which displays the Wordpress login screen, and then maybe show the user details or the like. I'd try to do the following:
- Instead of calling Vaadin UI by the callback URL, I'd create a new REST endpoint in the Vaadin app and make the callback URL point there. This way should clear the confusion of using multiple Vaadin sessions by accident. The callback URL should differ for every login request and it should include some identifier by which we can then look back appropriate UI class instance.
- Once you have the UI instance, just call ui.access(Runnable) and perform any Vaadin modifications or navigations you like, e.g. hide the browser component. These modifications will be shown in the browser next time the browser makes a request; or they will be shown immediately if you have Push enabled on your UI. You may need to catch and log the UIDetachedException if the UI was meanwhile destroyed. Controlling the code flow by catching an exception is definitely not nice, yet prior check whether UI.getSession() is null inherently includes race conditions and may still throw UIDetachedException, albeit with way lower probability.
Now the only outstanding problem is the problem of generating a String UI and mapping it back to the UI instance. I'm not aware of any better solutions to this; I also failed to find an API in Vaadin to find all current UI instances. Therefore I'd propose a simple homebrown approach:
- In your Vaadin UI code, when you create the browser component and generate the callback URL, create a new UUID and store it along with UI.getCurrent() into a statically-referenced ConcurrentHashMap<UUID, UI>.
- Make the callback URL contain this UUID, for example http://myvaadinapp:8080/rest/logincallback?uiid=93b0d7ea-2fe0-11e7-9365-bfc08b151fcb
- When the REST callback is invoked, extract the UUID and then the UI from the hash map.
- If the UI is not null, call access(Runnable) on it as described above and remove it from the map.
Now you will need to purge the map once in a while, to avoid memory leaks stemming from the fact that the user may abandon the login procedure, thus not invoking the callback URL. I'd walk the map once per minute and remove all UIs which has been added at least 15 minutes ago. Or even better, you can use ConcurrentHashMap<UUID, WeakReference<UI>> - this way Java GC will do the cleanup for you.
Please let me know if this is helpful :)
Thank you very much for your detailed answer. Unfortunately my vaadin know how is not very much. Therefore I have to ask for the individual aspects of your answer. The first question is how to create a REST-endpoint in my vaadin app. Unfortunately, I could not find anything about this subject.
Within the REST request to the worpress oauth-plugin I can not pass individual parameters. The callback delivers an authentication code for the logged on user with which I can request an access token. After receiving the access token I would like to get back to the original session. The acces token should be passed to the session.
Can you give me a suggestion.
Thanks a lot, Bernhard
actually REST are not part of Vaadin - you can simply use any REST framework you see fit, most popular are probably Jersey and RESTEasy. They will just plug in via web.xml or maybe by other means when you use Servlets 3.0. They have their own tutorials which should help you to employ them in your webapp, side-by-side with your Vaadin code.
If you don't want to setup REST services just now, another option is that you can redirect to your Vaadin app and e.g. use a special query parameter which you can then query for in the UI (or in VaadinRequest).
So, the callback URL is given and cannot be modified? What information will be passed down when the callback is made? Is it only the user name and the access token?
Actually, there is a complete project which employs both Vaadin and REST, you can find it here: https://github.com/mvysny/vaadin-on-kotlin
Just follow the tutorial to run it in no time. This class registers all REST endpoints: https://github.com/mvysny/vaadin-on-kotlin/blob/master/vok-example-crud/src/main/java/com/github/vok/example/crud/Bootstrap.kt#L66
This is an example of the REST service: https://github.com/mvysny/vaadin-on-kotlin/blob/master/vok-example-crud/src/main/java/com/github/vok/example/crud/PersonRest.kt
Just launch the app and test it by running