HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

What is the best approach for SSO and resource consumption via API v2?

We have an app that we would like to integrate with Vanilla via SSO.

jsConnect approach either for embedding or full-site is not useful to us since we intend on using API v2 to request specific resources and display them however we see fit.

How can we programmatically create or log a user in, while getting its access token?

Is there something like jsConnect, where we would set up an endpoint for Vanilla to request user info. Vanilla would then create a user or link it to an existing account, if email already exists, and reply with its access token?

This token would be used later by our server to proxy user requests. This way the end user's token never gets exposed.

How would you approach this? Does the user access token expire?

Thanks in advance,

Comments

  • R_JR_J Ex-Fanboy Munich Admin

    By now users have to create an access token manually which is not really an option for a nice UX. Somewhere in the docs there have been a hint that developers need to implement the creation of a token by themselves. Out of curiosity I implemented it, without taking much care about security!

    So you can take a look at the proof of concept I have on GitHub:



    The most elegant way I would say is to create a plugin for Vanilla like I did and call this endpoint via a form in your application so that your user sees a "Log in with forum" window and your app has to call the forums endpoint with this credentials once. After that it can use the token to access the API

    But I have no practical experiences with APIs and apps. The code above is just based on what I know about Vanilla...

  • Thanks for the help R_J! I read about creating a custom plugin in the forum and I was fishing for a different approach.

    That means I would have to handle user creation inside that plugin too, since creating them from the API is "strongly recommended against", right?

    I just want to be sure the implementation we're thinking of is feasible. Has someone else attempted something like this successfully?

    Thanks!

  • R_JR_J Ex-Fanboy Munich Admin

    That's the official documentation so if they say it's like that, I'd trust them!

    On the other hand, if you know what you are doing you can do everything. The main risk I see when not using the forum create user feature is that you might be missing restrictions which are made by any part of the framework or a plugin that will not be checked against if you do not use the official way to create a user.

    I would expect that creating a user will be possible in the future since Vanilla wants to be an API first web application.


    Vanilla itself ships with a plugin that creates users automatically. If you look at the Stub Content plugin, you will see that there is not much code required to create a user.


    You do not need to create a plugin. You can use the Vanilla framework directly. See this discussion for a few hints.

    With that you can

    a) create a token for every existing user in you app and store it in your apps database

    b) if Gdn::userModel()->getByEmail(...); doesn't return a user you obviously have a new user (don't forget to sync a mail change in the app to Vanilla!) and you can create it like it is done in the Stub Content plugin


    But I do not see any advantage in not making this a Vanilla plugin. I would even say, it should be a Vanilla plugin. Why use another framework from your code base? Keep it where it belongs to.


    If I had to do this task I would:

    • create an additional field in apps user table: vanilla_api_token
    • try to data from forum with this token
    • if it fails call vanilla/getUserToken (requires a custom plugin) which would return a token
    • save token to user table, repeat step 2

    The custom plugin should:

    • be an API controller itself which requires special rights (identified by a dedicated user token, that the admin has to create manually in Vanillas profile settings)
    • require POST, at least email address
    • respond with token or "user unknown"
    • if "user unknow" POST user info to vanilla/createUser
    • createUser() would insert new user and return user token (by internally calling getUserToken)


    You can cut it down to always POST all user info to the getUserToken endpoint, but I wouldn't do that. Re-authorizing wouldn't be that often and in such cases you can afford to do 2 requests instead of 1.


    The plugin advantage I see is that you do not need to have the forum on the same host as the apps code.

  • We're going to think about it. Thank you for your help!!

  • charrondevcharrondev Developer Lead (PHP, JS) Montreal Vanilla Staff

    We have an `authenticate` API behind the Feature.AuthenticationAPI.Enabled flag at the moment so it was on our radar. We've been caught up with other higher priority changes at the moment though, and that API endpoint is still missing some SSO integrations and an external security audit. If I remember correctly though, we did complete the JSConnect integration.

  • MunSemMunSem New
    edited December 2019

    How can I generate access token programmatically using javascript? so far i only found php example. It is really pain to look for example of sso via API

  • R_JR_J Ex-Fanboy Munich Admin

    If you are asking this because you have a node.js server: simply don't do it. You shouldn't recreate a frameworks feature with another framework. Use a plugin like described above to retrieve the token.

    If you are thinking of something which would work in the browser: that's technically impossible. Theoretically the browser would be able to create a token somehow, but if the token should be accepted by Vanilla, it needs to be stored in the database. Since a visitors browser cannot write to the database without accessing server side PHP, such a js implementation would be useless.

  • If I'm understanding correctly, I need to create my own custom plugin with an endpoint and call that endpoint from my application to retrieve the token for individual user. Is that the right way to do it?

Sign In or Register to comment.