How to authenticate users with Slack Direct Install URLs if they aren’t logged in to my application? - oauth-2.0

Slack provides the ability to make a Direct Install to install your application.
When you save your Direct Install URL, Slack will attempt to send a simple HTTP GET request to your declared URL. If it doesn't detect a HTTP 302 redirect pointing back to a fully qualified slack.com/oauth/authorize URL (see below), you'll receive an error letting you know.
...
First Slack sends the user to your Direct Install URL:
GET /slack/direct_install HTTP/1.1
Host: example.com
Then your server kindly redirects back to Slack's OAuth 2.0 authorization page:
HTTP/1.1 302 Found
Location: https://slack.com/oauth/authorize?client_id=12345.67890&scope=channels%3Ahistory%20users%3Aread&state=abcdefg
Resulting in the user jumping right into authorization. One point of friction removed.
You may continue to generate your own time or context sensitive state parameters and specific, pre-registered redirect_uri values as needed.
How does this integrate with my own apps user authentication? As I read it, the Direct Install URL must always 302 redirect to the Slack OAuth page. If the user isn't logged in to my application when they click the "Install" button, what am I meant to do?
My best guess is that I should:
Always redirect to the Slack OAuth URL and generate a state parameter to keep track of the request.
When the user finishes their authentication, they are redirected back with the code and state parameters.
If they aren't logged in, ask them to log in, and retain the OAuth code and state parameters. Once the user logs in, continue with the OAuth authentication process.
Is that right? Is there a way to force the user to be signed in to my app before trying to install the Slack app?
On a security note, for this to work with session cookies, I think they would need to be set to SameSite=lax, not =strict. The cookie wouldn't be passed from a cross domain request when they are set to strict.

I think you have a couple of options:
1) Don't use it.
The "Direct install" feature is a shortcut to the standard "Slack Button" installation process. Since in your case the user needs to first log into your app anyways, I think it would be more user friendly to also provide the Slack button in the same context on your webpage.
2) Return an error
If you detect that the user is not logged into your app, you could just return an error to Slack, e.g. http code 500. Slack should then also return an error to the user (not sure how it looks though). If you combine that with a clear message on your Slack App install page about the requirement to first login to your app that could work. This would be the easiest to implement, but also the least user friendly approach.
3) Request login to app after Slack login
After you completed the Oauth process and recognize that the user is not logged into your app you could request the user to login to complete the installation process. The disadvantage here is that your app would already be installed and could be left in an unusable state if the user failed to login at this point.
4) Halt Oauth process for user login
As you suggested you could halt the Oauth process after receiving the authorization code and request a user login to your app. Then continue the Oauth process after a successful user login. This can work if you need to take into account that the authorization code will expire after 10 mins. I do not see any way of forcing the user to login before he clicks on the direct install button.

Related

Getting "FacebookAds::ClientError (Invalid parameter: Terms of Service Not Accepted (fbtrace_id: Ch/RdwGB+D3))" after i call api to create App

I will explain the scenarios here
1) When user click on link facebook button facebook permission dialog is bypassed and returns back directly on redirect uri(http://localhost:3000/ in my case) with code and state.
2) I am successfully able to exchange the code return above with access token.
3) I used facebooks access token debugger to analyze the token above and shows be proper scopes i need.
4) After this i fetch ad_accounts id, page token and page ids using this token.
5) when i use this token to create campaign for ads i get the following error.
FacebookAds::ClientError (Invalid parameter: Terms of Service Not Accepted (fbtrace_id: Ch/RdwGB+D3))
I use ruby facebook-business-sdk.
My app is in development mode and not live yet.
I can see both facebook login and marketing api green live in my app dashboard.
It makes sense to me that i am getting "Terms not accepted error" as user is never prompted to permissions dialog to permit my app for token.
I also observed that if add scope params to facebook login uri, the user is prompted to permission dialog.
I must be missing some configuration here, i have not yet submitted my app for review.
Any help/clue is appreciated.

Via the api, can I force the user to login to reddit?

I am writing a Reddit client that uses OAuth to authenticate the user. One of the features I would like to implement is the ability to use multiple accounts simultaneously. This requires the user to authorize my client on each account they want to use. The problem I'm running into is that if the user is already logged into Reddit in their browser, when I pop a browser to perform the auth, it will have them authenticate my client against their currently logged in user.
Is there a way to force the user to re-enter their credentials? I would rather not have to put some kind of disclaimer on my Add Account screen that says "Please log out of Reddit in any open browser windows".
I tried opening the Reddit login page in a WebView so the request is sandboxed, and while that worked, it gives the user access to the entire login page (including all the links that navigate to elsewhere on the site). I don't mind that experience when I'm popping an external browser, but in an embedded WebView I really just want to present a username and password box along with the OAuth validation prompt.
Note: I do kind of prefer the embedded experience because it doesn't interfere with the users existing browser cookies, I just don't like how cluttered the login page is this way and I'm not sure how to prevent the user from navigating away from login. Also, for completeness, this is a UWP app, though this problem is largely technology independent.
The problem I'm running into is that if the user is already logged into Reddit in their browser, when I pop a browser to perform the auth, it will have them authenticate my client against their currently logged in user.
It may be caused by the authorization server. If so, we can not do anything in our client app.
But if it is not the server issue, in UWP, there is a WebAuthenticationBroker class witch can help you to authorize your app to access the user info from Resource server by getting a token. You can try to use the class to implement OAuth authorization. You don't need to use the in a WebView so that you can authorize your app with multiple users if you can manage all the user with the token properly in your code logic.
See the Web authentication broker topic and the sample to learn more details.

Auth0: How to enable silent authentication in Hosted Login Page?

I'm using hosted screen of Auth0. I want the following scenario to work-
Let's say I have 2 apps- app1 and app2.
One of the users signed in by providing email+password in app1.
User then navigated to app2.
Auth0 detected that the user has already signed in, so it redirects the user back to app2 WITHOUT having her signed in again.
But what I'm facing is this screen-
How can I save my user this additional click? How do I implement silent authentication? I know that you have to pass prompt=none to /authorize api, but since I'm not manually calling the api, how do I make the lock call /authorize with prompt=none?
What you want is silent SSO which is related to SSO but kind of independent.
The key is in the prompt param. This needs to be none in order for the user to not be prompted for login when he's already logged in Auth0's Authorization Server ("central SSO").
One annoying thing I found is that prompt is taken literally, so if the user is not logged in yet, he will not be prompted to login (you'd think it'd make sense to prompt the user when not logged right?).
In this case SSO will redirect to your app's /authorize with an error like "authentication required" and you'll have to handle it by redirecting the user to your /login endpoint again but passing prompt=true so that it knows that this time he'll have to pass prompt=true to Auth0's hosted login page.
To make things a bit uglier, currently passport-auth0-openidconnect seems to ignore the params you pass to the strategy unless you monkey patch one of the methods involved (I created a PR for it, don't when will be approved and/or if makes sense).
Essentially:
Pass prompt=none
If user is already logged in, he will silently be logged in your app as well
If user not logged in, user will be redirected to your app with "login required" error
In that case you'll have to pass prompt=true
I know it's a bit fiddly but I hope this helps you :)
PS: Another thing to bear in mind - I now just found out that it works perfectly when using Github as connection but when using google-oauth2 it blows up complain about the prompt param :|

dropbox oauth token flow: redirect without needing to click "allow"?

I am learning to use dropbox APIs and got confused when came up with the token flow.
As guide indicates, the flow should be like this:
the app redirect the user to a Dropbox webpage, i.e. .../oauth2/authorize
user logs in and approves the app
redirect back to the app. At this point, the app gets an access token.
However, when i requested the URL:
.../oauth2/authorize?client_id=xxx&response_type=token&redirect_uri=xxx
I was directly redirect to the destination with
REDIRECT_URI = "#access_token=xxx&token_type=bearer&uid=xxx"
And the "approve step" was skipped, i.e I got an access token without being allowed.
Is it a bug or my fault?
Any help would be appreciated :]
In certain cases, when the user has already approved the app to access their account previously, they will be automatically redirected through the app authorization flow.
If you want, your app can prevent this behavior from happening by using the force_reapprove parameter, documented for the /oauth2/authorize page here:
https://www.dropbox.com/developers/core/docs#oa2-authorize

Soundcloud as Oauth Provider: How to make it connect only one time

I'm currently implementing an Oauth consumer service which is going to use Soundcloud as an Oauth service provider as well. But I'm having the following issue with it: Taking Facebook or Twitter example, you go there, you sign in, you fill up the permission form, and you are redirected back to your app. If you go there a second time, and given you are already sign in, you basically skip all steps and are redirected back instantly. That means, Facebook recognized that you already gave permission to that 3rd party service, so it doesn't ask your permission constantly.
And that's what's happening when I use Soundcloud. Basically everytime I redirected the user to the Soundcloud Oauth connect endpoint, the permission form always shows up, even though I already gave permission to that 3rd party service previously. I'm forced to press "connect" every single time, which is a drag from the user perspective (how many times can you give permission to the same entity). My question is: is there a parameter I can use to make soundcloud recognize/validate the previous permission from the user account to that specific 3rd party service? Or is this Soundcloud Oauth design implementation and we have to live with it?
Edit:
Maybe this wasn't clear, but each time I press "connect" in soundcloud, a new access token is being generated and delivered. Since my app uses this access token to identify its users, it doesn't work very well for me that the access token is getting updated everytime I want to log in, making me effectively "sign up" everytime. To sum it up, I want to get the previously attributed token to my account, so I can look up in my database, identify it and log him in.
I'm also looking for a solution which doesn't involve storing state in the client that might get cleaned up.
What you can do is store the user's oauth token in local storage and reuse it in future sessions. That's what happens on soundcloud.com.
A longer explanation:
When you use the Connect flow, the user is authenticated by SoundCloud (either by using username/password, Facebook Connect, or an already-existing session on soundcloud.com), and then when it is successful, your app is given an oauth token for that user. This is passed to the callback page which is registered for your app.
That token is the only piece of information needed to have the user be "logged in". Unless the token expires (by time, or by the user manually revoking it), then you can reuse that in future sessions.
I think I'm a bit confused about your application's design: where and how is the oauth token being used? I think that instead of using the token as an identifier, perhaps the user's permalink might be better? If you have the oauth token, you can find out the permalink by querying api.soundcloud.com/me.

Resources