Connect a salesforce user to another salesforce user in another org without any user intervention - salesforce

We would like to connect a salesforce user to another salesforce user in another org without any user intervention from a service.
We have tried SAML Bearer Flow (using Remote Access Application) to connect to salesforce to retreive Access Token for one of our product. We are referring to the follwoing article.
http://help.salesforce.com/help/doc/en/remoteaccess_oauth_SAML_bearer_flow.htm
As referred by the SF article for this flow, it uses a previous user authorization to connect and retreive Token. In case the user (for whom Token is requested) has not already authorized the App, SF takes you to the Authorization page first and app will get the access token once app is authorized. This is working fine too. However it has this painful step of users authorizing the app before we can use this flow for the product. It would be good and simplified if this step can be done once for an org and the article does mentions that either User or Admin can authorize the app. However I am not able to find how an Admin can authorize the remote access application.
Does anyone knows and can guide how can an Admin authorize an App or is thre any other way we can achieve our requirement. Any thoughts will be really appreciated.

OAuth1 and OAuth2 require user intervention by design. Anything you do to defeat this would be circumspect and not best practice. You could make it easy on the user, but you will always have the initial "Authorize this app" message.
If you are trying to make it easy for the user to login to either org, then you may want to consider a hub-and-spoke SSO solution. See this doc.
If you are trying to pass information between two Salesforce instances, then you may want to consider Salesforce2Salesforce, or outbound workflow. However, this is done at system context, not user context.
If you want to maintain user context and security, you should consider the new Salesforce Canvas API. Canvas allows you to call an outbound service, and pass credentials to the service so that it can communicate back. There is no reason the foreign service could not be a Salesforce instance.

Related

Why do I need two AAD applications just to add roles into an access token?

As shown by many samples I have two AAD application registrations, one for my javascript-based front end, and one for my JSON-only web APIs.
If I fully trust my client AAD application, why does AAD require me to create a second AAD application for my web APIs?
For example, assuming I add specific roles to my client AAD application, if client signs in with AAD and gets an id token and access token containing my roles, it only needs to send the access token to my APIs. The API only needs to crack the JWT, validate the audience, issuer, tenant, roles permissions, and signature. In this world, no client secret is needed in the web APIs, a second AAD application registration not needed, and still no call to AAD from my APIs. Unfortunately, without two AAD applications, I cannot figure out a way to have AAD include roles into my access token.
If I didn't fully trust the issuer from mucking with claims, I can see why I would need two AAD applications and a client secret. But since I do trust my AAD application and the signature of the JWT, why the extra complexity? Or maybe there is a way to do this that I haven't found?
Thanks!
Responding to Marc here because just not enough characters in the comments field -- The sample you referenced is an excellent sample, specifically the JavaScript one calling the Web API. It is what I am doing right now in fact. However, the problem is that Web API in the sample is open to anybody who has authenticated on the tenant. I need to secure the Web API down to certain individuals in the tenant, and simply checking the client/app id is not sufficient as anybody who can create an AAD app can fake it.
So what I need to do is have roles added to the the access token so I know that my application authenticated the user, and that user has been granted the required roles. For example, here is a Microsoft sample. And even here a Microsoft video walking through the process.
If I don't have two AAD applications w/client secret, the roles claims is never provided in the access token. It is always provided in the id token, but not the access token.
I feel like I am missing something obvious here. If AAD would just put the roles I requested into the JWT when I authenticated against it, and I validated its signature, audience, issuer, and roles, I wouldn't need any of this extra complexity?
Ah, I think I understand where you are going: you would like to control which users can access an API, no matter what client app they are using to access the API with. That's a function of the API - you cannot control that through AAD. In AAD you can control which users can access which applications (UI) using either user access restrictions (enterprise tab) or role-based access. However, access to an API is controlled in AAD at the calling application level via scopes. APIs are never accessed directly by users but only by other apps so controlling access permissions at user level would cause admin havoc. So, you can control what permissions a user has in the app they are using and you can control what permissions that application (client) has in other applications (APIs, resource servers) it is using.
In other words: role is about user access to UI, scope is about one apps' access to another.
App secrets provide added security for getting tokens - they have no bearing on what permissions are included in the token.
Can you provide a link showing that two apps are needed? That should only be the case if the API you want to call is not provided by the web app which served the JS to the browser. None of the 'official' samples require you to register two apps (Graph API, used in some of these samples is a separate API and it is already registered). A problem with tokens passed from the browser is that they were acquired by a public client, not using any secrets apart from user creds. Therefore, they are easier to steal and re-use. Your own back-end app may want to use a secret to get its own token (extension grant) to call yet another API using a token that does not reside in a public client.

IdentityServer4 and external check user

Im searching solution about authentication.
I found IdentityServer and Im trying understand how it works.
In my case I need to check user exist in another app.
I have old project created in asp.net web froms and this project have a users collection stored in db.
Now I must create client who will be call to WebApi and in this WebApi I need to authenticate user. I want to do this using IdentityServer4. Can I in IdentityServer call to my old application or db this application and check user by custom method?
In future I want connect another application to IdentityServer and this new application should have users in IdentityServer, so I will be have two places where I will have users for two application. I need to be sure I can check user exist in this two ways.
When request will be form new app IdentityServer should check user in his db and if request is from client who will be call to old app should check this user in external app(db).
Example call:
enter image description here
I dont know I good understand idea of IdentityServer, but generaly I think this is not good solution for my case...For now I understand I can store users in database but only with Asp.Identity in IdentityServer.
What do you think about this case ?
In future I want connect another application to IdentityServer and this new application should have users in IdentityServer, so I will be have two places where I will have users for two application. I need to be sure I can check user exist in this two ways.
When request will be from new app, IdentityServer should check user in his db and if request is from client who will be call to old app, should check this user in external app(db).
The short answer is that IdentityServer4 is just an implementation of the OpenID Connect protocol and the persistence and authentication of users is entirely customisable so you're free to implement that any way you like.
As for where to keep your users - that will depend on your problem domain and business rules but I'd probably try and avoid using multiple DBs if possible and instead migrate existing users from legacy applications to your identity service's own store and take care to only bring over identity and authentication information and not access control/authorization information. i.e. keep the authorization logic in your client applications and APIs.

Why do i need to create a Multi-Tenant App?

I have been doing some R&D on using the MicrosoftGraphAPI to fetch the skus subscribed by my organization.
I have created an app as described in the documentation. I did all the steps in the above link except 'Assign application to role'.
Using postman am able to get the oauth2 token by sending a post request using the link
https://login.microsoftonline.com/<mytenantid>/oauth2/token
with the client_id, client_secret, resource(https://graph.microsoft.com) and grant_type(client_credentials) parameters.
After this token is obtained I can fire a get request https://graph.microsoft.com/v1.0/subscribedSkus with the Authorization header set as Bearer {token} which will return the SKUs subscribed by my organization.
So far so good. :-)
Now the requirement is I need to fetch the subscribed SKUs by one of the client (let's say having the azure ad tenant id 'ABCDEFG') of my organization.
I can successfully do that by registering an app in the client's tenant 'ABCDEFG' with the same steps as above.
This approach is fine if my organization has say 1 or 2 clients.
However, if the client numbers are more than say 30 this approach of registering an application in each Azure AD instance is not feasible.
If the application that I registered in my organizations AAD was multi-tenant then how should it help me?
What will be the steps needed to obtain the access token for each tenant?
Can somebody assist with some detailed explanation?
Since you need application-level access, you would assign one of the Application permissions listed in the documentation for getting SKUs: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/subscribedsku_list.
Directory.Read.All, Directory.ReadWrite.All
In this case you should require the Read Directory Data (Directory.Read.All) application permission.
Then you mark your app as multi-tenanted.
Now then in order for another org to use your app, they will have to be on-boarded.
You will need some kind of page where their administrator can click a button/link to start using your app.
This should redirect the admin to:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=your-client-id&prompt=admin_consent&response_type=code+id_token&redirect_uri=url-where-to-send-user-back
Once they sign in, they will be presented with a consent screen, where they can approve the permissions that your app requires.
If and when they do that, they will be redirected back to your app (to the URL you specified) and you can use the Id token to know which Azure AD tenant registered.
During this process a service principal for your app is created in their tenant, and the required permission is granted to it.
This means you can then get an access token for their tenant from: (using the same credentials)
https://login.microsoftonline.com/their-tenant-id/oauth2/token
Remember that access tokens are specific to an Azure AD tenant, so you will have to get an access token for each tenant.
One thing I would like to point out is that you should instead try to use delegated permissions if possible.
The application permission given here gives quite large access to your app, and some admins might not use your service for that reason alone.
Delegated permissions are more complex to handle, but allow your app to act on behalf of a user instead of purely as itself.

How should you secure a multi-tenant API with Identity Server?

I'm struggling with the correct way to secure a multi-tenant Web API with Identity Server. Let me explain.
We have a multi-tenant Web API that serves a ASP.NET MVC application.
Each new customer is assigned a new TenantId.
A customer can have multiple subscriptions of the application. Its
the same as saying that the app manages multiple databases per
customer (that he can access from the same base URL).
Each user belongs to a single customer (tenant) and will have access
to all that customer's subscriptions.
The API is set in a way that every endpoint includes both the tenant id and the subscription id so it can know from which subscription/database it should get the data.:
<server>/tentantId/subscriptionId/(...)
Now imagine that I have another external app (say a console app), using the client credentials flow, that is trying to access some API resource "on behalf" of a customer, meaning that will use a specific tenantId/subscriptionId pair:
<server>/1000/1/products
Every time a call hits one of the API endpoints I need to validate that this specific client app can access that tenant/subscription.
It would make a lot of sense if the Identity Server could perform that check automatically as part of the authorization flow.
If we added some way for the customer to register (consent) a specific client app to access the Web API on it's subscriptions, may be we could also set the Identity Server to know that in the form of scopes or at least include that information in the claims so that we could perform the permission check by inspecting the token instead of calling an external component.
Is this even possible?
Should I try to use scopes? Claims?
Can anyone point me in the right direction?
Your question is confusing when you talk about multi-tenancy. Isn't an API multi-tenant by default? The way I see it, it's a resource that can be accessed by multiple users / clients.
If I understand correctly, all you want is to access the API through the MVC app on behalf of a user. In other words: a hybrid flow with API access.
Instead of putting the userid in the path, use the id from the sub claim. Which lets the API distinguish between calls on behalf of clients and calls on behalf of users.
The resource should take care of authorization. Depending on the type of authorization you can use claims. If a subscription needs to be checked then this should be done by the API, using the sub claim to distinguish the user.
Scopes on the other hand are meant to define the resource. With the scope "api1" I can access the Api1 resource (api). But it says nothing about authorization.
IdentityServer provides Authentication as a Service.
It is your apps' duty to provide the actual Authorization.

SalesForce to emulate a google session login

I'm pretty new to SalesForce and their Apex language. I've been reading some documentation and tried the integration between Google and SalesForce.
I'm wondering is it possible to emulate an auth token from google to SalesForce?
I'm trying to read a google spreadsheet and then fill up a SalesForce object automatically. The user login will always be the same/universal for this spreadsheet, so I have the credentials required to login.
I am working off of the sample that requires a visualforce, and I'm wondering how would I automatically do the session id token that the google spreadsheet API requires.
Any ideas?
The old-school, hard way would be to send a login() call to the API (available through SOAP messages). Salesforce API is well documented and plenty of examples are available (both in programming languages and for raw XML requests/responses).
But I have no idea what possibilities you have from Google side, if it's only JavaScript then you might not be able to send and retrieve AJAX-like calls to another domain...
Recently another option emerged and that is REST API (no SOAP needed). Looks more promising and easier in my opinion. Quick intro is available here and you'll find more documentation on the bottom of the page.
Last but not least - 2 interesting links:
http://code.google.com/apis/gdata/articles/salesforce.html for some integration tutorial
and built-in integration offered by Salesforce: http://www.salesforce.com/assets/pdf/datasheets/SalesforceGoogleApps.pdf
I've used custom settings to do this. Use OAuth to get a token for Google, then store that token in Salesforce custom settings (Setup-Develop-Custom Settings). You can then retrieve the token for callouts to Google from that custom setting for any user needing access to Google Apps. The downside is, every user will authenticate as your custom setting token user. The upside is that they won't need to individually authenticate. Custom settings are retrievable via Apex using a simple getter, and live as Apex-like objects.
Also keep in mind, Google requires each service to use it's own token. So, if your user wants to use Calendars and Spreadsheets, that's two separate tokens that will need to be stored and retrieved for the callout.
I generally allow users to create their own authenticated session tokens via OAuth if they want to do that, then failover to the custom settings to get the general admin token if necessary.
Are you trying to log into Google Apps from SFDC? There are options for Google Apps within Salesforce, go to Setup > Administration Setup > Google Apps > Settings. I've not used this and it requires some setup, but thought I'd point it out. Aside from that I can only blurt out OAuth (getting users to authenticate with Google from within Salesforce when trying to access Google Apps) and SSO (which I know can be used to authenticate from an external system, though not sure if it works the other way).
Look into the "Named Credentials" menu in salesforce setup.
There, you can store auth credentials for the services accessed via Apex:
"A named credential specifies a callout endpoint and its required authentication parameters. When setting up callouts, avoid setting authentication parameters for each callout by referencing named credentials."
a username/pass combo can be used, or a certificate, or an AWS signature, and there is a JWT option..
Help docs: https://help.salesforce.com/articleView?id=named_credentials_about.htm&type=5

Resources