How can my app (an iframe loaded by salesforce) confirm that the user is logged in to salesforce? - oauth

We're building a salesforce app, and I need to auth against a user's SF user (so they don't have to log in to SF, then also log into our system).
So I from our app, I want to bounce off of SF and:
1) confirm that the user is logged in to salesforce.
2) get (or confirm, if I provide it) some kind of tenant id, so I can confirm that they are logged in to the tenant they are self-reporting to me.
Does SF have docs on this flow somewhere?
Thanks!

When you put your iframe in Salesforce you can include the current SessionId and ServerURL in the query string parameters.
You can then use the PartnerAPI with these credentials to call back to Salesforce and verify the users details.
There are some very basic details on doing this in Implementing Salesforce Integrations on Force.com

Related

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.

Using OAuth but store extra information in my own DB

I've been looking into OAuth for a while, but haven't implemented it in any of my applications yet. I'm having trouble really understanding the full concept, so I still have a few questions that I haven't found an answer to, so I hope that anyone can help me.
I want a user to be able to start my application (WP8), login to facebook / twitter / microsoft / ... .
When he gets authenticated, I want to actually save this user to my own DB so I can add some user specific stuff like preferences, posts, ... .
What do I need to save in my own DB to specify a user?
Do I need to save the token itself or is this something that will be invalidated after a while? Or do I need to specify the user's name? With other words: What can I use as a unique identifier?
And what happens when a user would authenticate with for example facebook and he deletes his account?
And one more question, would you ever allow a user to connect to an application with 2 different service providers? If so, how would you make the coupling of these 2 providers to 1 user in your own DB?
I hope my questions are clear enough!
If not, don't hesitate to ask for more information!
Kind regards,
Gert
I assume that you have your own back-end where you authenticate your own users and your WP8 application is just a client.
First, let me distinguish between a user credential and a user profile. User credential is something that validates who the user is, e.g. username/password, facebook user id supplied with a valid auth token. User profile, is what you store in your own database about the user.
You also need to distinguish between a token you use to authenticate the user and the AccessToken Facebook needs to grant you access to user's data.
So... to answer your questions:
What do I need to save in my own DB to specify a user?
Create a record with user data (like preferences, and your unique user ID), and user's login method (e.g. Facebook) and credential (e.g. Facebook's user ID). This is your user's profile.
Do I need to save the token itself or is this something that will be invalidated after a while?
You can also store the Facebook AccessToken here if you've been granted "offline access" privileges by Facebook, but that is used for Facebook's access by you... not by the user's access to your app/back-end. For user's access you could just use a mechanism similar to cookie-based authentication - it's up to you. You could use the AccessToken as a kind of a "cookie", but you would need to always check against Facebook that it's valid.
With other words: What can I use as a unique identifier?
You could treat Facebook's ID as unique (so long as you never allow another account in your user profile DB to link with the same Facebook account)
And what happens when a user would authenticate with for example facebook and he deletes his account?
It's a good idea to have users still create a username/password combination that works with you site and only rely on Facebook login for convenience. In any case, Facebook provides a "Deauthorize Callback URL" when you create an app profile on Facebook. This is called when a user deactivates your app or deletes an account with Facebook. When you receive this call, you could send your user an email when an auth link to setup a different credential so as to not lose access.
would you ever allow a user to connect to an application with 2 different service providers? If so, how would you make the coupling of these 2 providers to 1 user in your own DB?
Sure, you could do that. Say you'd want to allow a Twitter account as well. You'd need to add a Twitter user ID field to your user profile database.
Here's another tip: create an ASP.NET MVC4 project in Visual Studio - the template includes an example of how to set up a user profile database with OAuth login.
Hope it gives you the high-level overview to investigate further.

Is it possible to be able to correctly select any available Google account to use when using authorisation via the JS client library for Drive?

I've got an existing Google Drive enabled application that's using the Google Java client library and server flow auth.
If you're not logged into the application and navigate to the URL AND you have logged into more than one google account on that browser (only one personal Google account is possible, any additional ones have to be Google business accounts) the OAuth callback offers the options to select which Google Account to use.
However, whilst testing a switch to using the JavaScript client library I'm not able to activate the multiple account selection screen using gapi.auth.authorize. Is it possible to handle multiple accounts using the JS library?
Update : I tried with the immediate parameter false. I can log in as long as I don't change account in the popup. If I do change account, I get to:
https://accounts.google.com/o/oauth2/auth?client_id=433863057149.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/drive.file+https://www.googleapis.com/auth/drive.install+https://www.googleapis.com/auth/userinfo.email+https://www.googleapis.com/auth/userinfo.profile&immediate=false&redirect_uri=postmessage&origin=https://drivedrawio.appspot.com&proxy=oauth2relay593063763&response_type=token&state=701344514&authuser=1
in a new tab and nothing happens. I've made a video to demonstrate.
Update 2 : This bug against the JS client library for the need for double selection of mulitple account has been accepted.
You are not getting the multi user selection screen because of the following parameter: authuser=0
This automatically selects the first account you are signed-in with (authuser=1 would select the second etc...).
It's currently not possible to remove that param using the client library because the client library sets it automatically to 0 (this is why it claims not to handle multi-accounts) if there is no value so one way is to override it to -1 for example, this will show the multi-account chooser. Then you could also ask to access the user's profile or email at the same time you ask access to other APIs and fetch either the email of the user or its ID. Then on subsequent auth you can specify the user_id param which wil bypass the user-selection screen.
So in practice, first authorize like this:
gapi.auth.authorize({client_id: <Your Client ID>,
scope: 'https://www.googleapis.com/auth/drive openid', // That requires access to Google Drive and to the UserInfo API
authuser: -1});
The only problem with the above is that the auto-refresh of the client library will not work because every auth will by blocked at the multi-account selection screen.
The trick is to get the ID of the user using the UserInfo API, save that ID in a session cookie and use it on subsequent auth like that:
gapi.auth.authorize({client_id: <Your Client ID>,
scope: 'https://www.googleapis.com/auth/drive openid',
user_id: <The User ID>,
authuser: -1});
Specifying the User's ID will make sure the multi-account chooser is bypass and will allow the auto-refresh of the token from the client lib to work again.
For reference, other URL param that impact the User flow are:
user_id: similar than authuser (bypasses the multi-account selection screen) but you can use email address (e.g. bob#gmail.com) or the User ID you get from our Open ID Connect endpoint/Google+ API/UserInfo API
approval_prompt: default is auto, can be set to force to make sure that the approval/grant screen gets shown. This makes sure that the gant screen is not bypassed on subsequent auth (after first time).
immediate: immediate is a bit tricky, when set to true it will bypass the grant screen (kinda like approval_prompt=auto) if the user already granted approval previously, but if the user has not granted approval previously you will get redirected with an error: error=immediate_failed. If set to false it won't add special behavior and therefore fallback on the behavior setup by the approval_prompt value.
Note: immediate=true and approval_prompt=force is an invalid combination.
I think the client library is using the immediate param so that if he gets the error=immediate_failed it will restart an auth flow without the authuser param, but that's only speculations :)
The OAuth grant access page is only shown when not in immediate mode, does it work as expected if you set the immediate parameter to false?
According to http://code.google.com/p/google-api-javascript-client/issues/detail?id=11
multi-login isn't supported by the Javascript client
Pay attention to authuser parameter. Set this to "2" for example and you will be prompted for login even if you are authenticated already.

Multi login problem using Twitter and Facebook Oauth

I am adding Twitter and Facebook login to a MVC 3 test application using TweetSharp and Facebook C# SDK.
Currently when a user signs in using Twitter I create a user account for that user in a user table and store the id, token, and token secret in a separate table with a foreign key to the user table. Since the id, token and token secret do not expire I can quickly locate the right user account when the user logs in next time using Twitter.
What if the very same user logs in using Facebook next time? Since Twitter does not provide email in their API and I therefore have no common piece of information to tie a user account to either Twitter or Facebook I assume I have to create a new user account for a Facebook login? Does anyone have any experience with this? Are there any ways to solve this?
I identify each user internally with a unique key. I check cookies for the user key when any user hits the site. If there's no cookie I create a new key. add it to the user database and set a new cookie. Once a user completes registration the first time by logging in with any of Facebook, Twitter or .Net membership , that key is forever married to that user.
So when an existing Twitter user logs in for the first time with Facebook, we know who they are because their user key exists. It is basically the same solution as macou suggested. Macou's has the plus of working on a new machine or if cookies are cleared, the cookie solution has the plus of not requiring additional user input.
Not really a solution, more of a work around. I was faced with the same problem and ended up forcing the user to complete thier account profile by asking for their email address before allowing them to proceed any further. This meant that if the email address coming back with the Facebook auth matched the email address created with the twitter signin then I didn't need to create another account.
The bigger difficulty was coming the other way, if the account was created by the facebook auth first. It meant an untidy marry up of accounts.
To be honest the information we got from allowing users to sign in with twitter was not worth the effort and in the end finished up only allowing Facebook auths. I'm not sure how important twitter is to your solution.
Not the perfect answer I know, but I thought I would share my experience.
You can't use just a cookie because I can login as facebook then my wife login as twitter using the same browser, you shouldn't link the two accounts in this case.
I think you need to do more than that:
Use a cookie then
Use name/first name/login name/... to see if they match.
Example:
Cookie id: 18459439731114330636, find user with id = 18459439731114330636. Found, go to 2, not found, go to 3.
Is username/first name/last name/... matches the current user? if yes, link accounts. if not, go to 3.
Create a new user.

How do I associate my facebook app user with my web app user?

I have a facebook fbml app and a web application. I want my web application users to be able to add my facebook app. Seems simple, right?
Currently, I am making the connection by adding a param to the canvas page link in my site. For example, I have a link that says "add our fbook application" which links to http://apps.facebook.com/our_fbook_application?suid=786432878923
suid is the logged in user's uid on my site. Adding this to the canvas link params allows me to connect their site uid to their fbook uid on my site. This way when requests come in from facebook, I can authenticate them based on solely the fbook uid after the connection is made.
This seems like a security issue. I think an attacker could log into their facebook account and guess user id's by calling http://apps.facebook.com/our_fbook_application?suid=x and when x corresponded to a suid on my site, he would be authenticated to see that user's data.
This connecting of a facebook app user to a website user seems like it should be really common practice, but all I can find these days is facebook connect examples which I am not supporting yet.
Can someone walk me through the steps to connect a facebook app user to my website user? Major bonus points if someone can do it in Rails with the facebooker gem.
Thanks!
don't pass the suid as a variable.
Instead, on your backend, associate the FB uid with the suid.
When the user accesses the app via website, he/she will have to log in (maybe through fb connect?).
When the user accesses the app via FB, your page should be able to determine the fbuid of the user and map that to the correct suid and log the user into your site.

Resources