Gsuite App integration: Identify company/domain of user - oauth-2.0

I'm integrating my web application into gsuite (fka google apps marketplace) and I'm not sure how to handle the user creation flow.
At first the admin of a domain adds my app and goes through the initial authorization steps (scopes, TOS,notify users). As far as I understand there is no communication with my site at this point.
At the end of there is a link urging the admin to complete the setup on my site.
When the admin opens this link I can run him through oauth and get his tokens.
But this is where I'm stuck now:
How do I identify the domain/company the admin and company users belong to?

Not 100% happy, but this is what I ended up doing:
After receiving the tokens, I fire of a request to plus/people api and explicitly require the domain field.
var fields = 'id,name,language,domain,image,emails';
plus.people.get({ userId: 'me', auth: client, fields:fields }, ..
The domain is then what I use to identify the company with.
The customerId would be better, but I have not found a way to retrieve it without being a google admin.

Related

FusionAuth - Invite based user on-boarding with social logins

We create users with their email address. We send email to each user with a link to change password api with changePasswordId. When user clicks the link, he will be redirected to change password screen where he can set the password and access the application. This works.
But, now we want to allow users to register with their social Idps upon receiving invitation/verification email. Can't see any fusionauth documentation on this part.
Questions are as follows
How to let user select their social Idp while verifying their email?
Can a user have multiple logins with different Idps for one application in FusionAuth?
Is there any linking api which links all external user accounts with their fusionauth user account?
The flow we are expecting is :
Invite User -> User clicks link -> User will be presented with set
password and social logins-> User chooses google -> Google
authenticates user and returns token back to fusion auth -> fusion
auth links user's google account with already created (invited) user
account. -> Next time user logs in with google account -> Fusion auth
identifies the user and allows him to access the application.
Updated :
Let me try to explain our situation and need, with less focus on the password setup task:
We need to set up new users that are associated with google based education accounts on custom school domains. Teachers and students that might have addresses like first.last#middle.school.com We need to take the class roster from Google Classroom, initialize accounts for each student in our backend via our API which also creates FusionAuth user and app registrations for each.
Schools don't often want kids setting passwords on vendor sites. When we send the account confirmation / verification email to the new cohort of students they would ideally be directed to the approved and configured method for that domain (perhaps Google, Microsoft, other SAML or password). If we can't get selective about the confirmation method shown after the student provides her invited email address then we could present multiple confirmation options on the same screen and let the teacher direct the students to the correct choice.
But in summary we need to avoid requiring password setup and support confirmation with the invited social account when required by the school.
If I understand your use case correctly, what you want is to add the "Login with Google buttons" to the Setup Password workflow. This is different than the Email Verification workflow, so if you are looking for a way to log users in with their social profiles during Email Verification, that's something completely different. In fact, I don't think that is a use case because after the user verifies their email, they need to log in again and they can do that using their social profile.
Unfortunately, FusionAuth doesn't fully support the ability to allow someone to use the Setup Password workflow using a social login. It might be possible though using the Email Templates and Theme editor in FusionAuth. I haven't tested this, but you could try it and see if it works.
What you would do is to pass in a URL parameter to show the social login buttons during the Setup Password workflow. This would be something you could do in the email template for Setup Password like this:
Click this link to setup your password:
<a href="https://example.com/password/change/${changePasswordId}?showSocial=true">
Setup Password
</a>
Then, using the Theme editor in FusionAuth, you would add some code in to show the buttons like this (the ?? part is to handle when the parameter is missing):
[#if showSocial?? && showSocial]
show social buttons here
[/#if]
You could give that a try and see if it works for your use case. If it doesn't work, you can always open a feature request for this on our GitHub issue tracker and we can see if it receives enough upvotes to get on the roadmap. You can also engage FusionAuth professional services to build this feature for you as well.
For your other questions, you can have as many logins with external IdPs as you want for a single user. The user is unique by their email address.
I'm not sure what you mean by "linking api", but if a user logs in with an external IdP, their tokens from those external providers are stored on the user object. You can look up those values and then call third-party APIs with their access_tokens.
UPDATE 8/27/2019
Ah yes. The social login buttons do require all of the OAuth parameters, so this solution won't work because those parameters aren't part of the Setup Password workflow.
I guess I'm confused on how this actually works and whether or not this is a workflow FusionAuth should be handling. Social logins aren't generally used for account verification. They are normally used for account creation. For example, you could just send the student to FusionAuth before their account is created, they login with their Google classroom account, and then they have a FusionAuth account. Is there any reason the student can just login in after their account is created? Is that not essentially the same thing?
Could you do something where students that have accounts in Google Classroom are created in FusionAuth with a randomly generated 32 character password (for security) since they will be logging in with Google regardless. You can then just send them an email with a standard login link.
For students that login in with a username and password to FusionAuth directly, send them a Setup Password email. This will let them pick their own password.
In terms of account Linking, FusionAuth links accounts automatically based on email address (the unique login identifier actually). Therefore, you don't need to call any extra API to associate the social login with a user.
I might still not be clearly understanding the use case, so feel free to contact us directly using the form on our website. We might need to setup a web conference to discuss your needs in detail.

Granting users.read.all permission to all users in the domain

I was told by one of the engineers at Microsoft that in order to display the jobtitle field, using users method in REST, I need an admin permission. I would appreciate if someone can answer exactly what steps the domain administrator needs to take in order to give user.read.all permission to all users in the domain that will run the graph query. I would appreciate if anyone can provide detailed step by step instruction.
For user.read.all, you will need to get administrative consent from the organization before a regular user can sign-in to your application.
To do this, you'll first need to have them go through the “Admin Consent” workflow. This workflow requires an administrator but once complete any users of your application will have “admin consent” to the restricted scope.
For example, you would normally you would then authenticate users by redirecting them to
https://login.microsoftonline.com/common/oauth2/authorize?<your params>.
Since this scope requires an Admin however, you fist need to obtain consent by first having an Admin authenticate by redirecting them to
https://login.microsoftonline.com/common/adminconsent?<yours params>.
Once an Admin grants consent, normal users will be able to use OAUTH to authenticate.
Dan's link took care of the problem.
In the link the below sample link was the answer. Instead of the word "common", I have replaced it with the tenant ID as shown below:
https://login.microsoftonline.com/{tenant id from azure ad}/adminconsent?
client_id={application client id}
&state={can be anything. I used the same as the redirect url}
&redirect_uri={URL that exactly appears in the app application portal}

How do I test a Azure AD protected Web API in with Visual Studio Test Adapter?

I've created a multi tenant Web API that works just fine. Now I want to build a native client for testing. The Web API app is defined in one tenant. The test app is defined in another tenant that has given admin consent to the Web API.
I want to use the native app to authenticate with username and password in my (non-interactive) integration tests. I cannot use certificate/app-only authentication because I need a real user context.
Getting a token
var userCredential = new UserCredential("admin#clienttenant.onmicrosoft.com", "password");
var context = new AuthenticationContext("https://login.windows.net/common");
return context.AcquireToken("https://webapitenant.onmicrosoft.com/webApiResourceUri", testClientId, userCredential).AccessToken;
The problem with this code is that it doesn't work until I've given admin consent to the native app, even if the user is in the same tenant as the app registration.
Exception thrown:
'Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException' in Microsoft.IdentityModel.Clients.ActiveDirectory.dll
Additional information:
AADSTS65001: The user or administrator has not consented to use the application with ID 'nativeclientid'. Send an interactive authorization request for this user and resource.
Since tests aren't interactive I have to create a console application that uses the above code but with PromptBehaviour.Always. This will prompt me for username and password and show a consent form. After I give consent the tests that is using the same native app registration starts working.
Is there a way to accept the consent form without a interactive GUI?
At the moment there is no other way to write user consent without some sort of user experience. (Which makes sense right?)
If you use the Azure Management Portal, as an administrator of your tenant, all the apps you create should automatically be consented for the resources you selected. This is because the Azure Management Portal specifically will write those consent links as you save your client application.
If you use other portals or APIs to create your application, then you will need to consent to the application at least one time. You do not need to necessarily put prompt behavior on your application to get the consent screen. You can just generate the URL for signing into your application, which will also take you through the consent experience:
https://login.microsoftonline.com/<TenantID>/oauth2/authorize?client_id=<AppID>&response_type=code&redirect_uri=<RedirectURI>&resource=<ResourceURI>&prompt=admin_consent
Note that we added a "prompt=admin_consent" at the end which will consent to the application on-behalf of the whole tenant. With this kind of consent, you will only need to do it once per application to get it working.
I hope this helps!

Create User-object in custom user-database with 3rd party OAuth-token?

We are creating a service (backend + iOS-app for now) where a user can log in. We have completed our own custom token-based login system with registration. We are now trying to implement the function where they can select to "Log in via Facebook" or "Twitter" etc. (I.E not using our custom registration with username and password)
We have successfully implemented the client-function, but all we receive from the 3rd party service (Facebook) is a token, and the user's basic information.
To use our service, it is (of course) required to have a proper CustomUser-object (our own) registered on our server, which generally would be created on our custom registration. When logging in through 3rd party service, how should we create a CustomUser-object for that externally authenticated user?
When the user is authenticated by a 3rd-party service through our application, how and what do we send to our own server to register (or authenticate)?
We receive an auth-token (which will eventually expire), and the app (client) has access to the user's basic information on the 3rd party. We were thinking of sending the basic information, such as the user's user_id and email along with the token, up to our own server and create a new user-object for it if it didn't exist before. However, we realized that this wouldn't be very secure at all. When the user logs in to our service the next time, using the same 3rd party authentication, we only have the users user_id and email to match. The token might be a new token. Which means that anyone intercepting any 3rd-party login-calls to our server will see that the only information needed to log in to an existing customUser based on a 3rd-party authentication is the user_id and an email. Which are very public on most such 3rd-party services, such as Facebook.
We've been trying to read up on OAuth and authorization/authentication using these 3rd-party services, but every single documentation we've seen is painfully focused on the 3rd-party authentication and doesn't touch the subject of our own authentication of the 3rd-party authentication..
Are we going about this all wrong?
Actually, the assertion you made about email and user_id is not totally true, at least for Facebook.
... Which are very public on most such 3rd-party services, such as
Facebook.
When somebody logs in through Facebook Oauth service, you'll get back an "app_scoped_user_id" which is a unique ID that Facebook creates for the user and your App. Each user will have a different "app scope user id" for each App he uses and nobody except you (the App) will know that "app scope user id".
App scope user id docs
So I'd say using the "app scope user id" as identifier of your users is secure and the best way to do it.
Not sure how it works with other services like Twitter but I'm pretty sure you can do something similar. Even if the user_id is public, it should be always unique and you can use it to identify your own users.
I hope it helps.

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.

Resources