apex how to login to another application from link in one application? - database

I have two applications in my workspace, APP 1 and APP 2.
In my case, user will log in to APP 1. from there, i put a menu(or a link) to APP 2. however APP 2 requires authentication. So it will take me to a login page. i would like to eliminate that and get the current user's credentials on APP 1 and login to APP 2.
i'm looking for a simple straightforward method (but need to consider security) to login to APP 2.
what i could think of is apex_collection..i could store credentials n use it to create a login process for APP 2. however apex_collection is session based. eventhough i've set session for APP 2, it still wont read values from my apex_collection.
Does anyone have a suggestion or a solution?

All you need to do is use the same authentication scheme in both applications and set the cookie name attribute to the same value in both authentication schemes like this:
APEX will then use the same session across the two applications and the user will not have to log in again when they navigate from one to the other, provided of course that you pass the SESSION_ID in the URL.

A Few Comments on Default APEX Workspace Authentication Security
It may also be helpful to expand on an explanation of why the solution posted by #TonyAndrews works.
For any Apex Apps within the same workspace, if they use the default "APEX Application Authentication" method, they will consult the same authentication user list... so USER1 and its password is a valid login for any of the "neighboring" applications...
This may be a concern if you are hosting different clients or users that should not be intermingling with the other applications. You can also define user GROUPS in the same place as you set up each workspace user. Each application can have its own security filter that permits access by membership of BOTH user/password authentication AND membership in the appropriate access group.
Sharing workspaces may also be a problem because of the unique user name restriction of a single workspace. You can get around that by:
Defining different name-spaces for each application:
Email addresses are good: "someuser#sampledomain.com"
An app id prefix such as: SHOP_EDNA, SHOP_GARRETT, TC_KAREN, TC_MARLOWE, MY_BORIS etc.
Different name styles: first name only, first name + last initial, etc.
To keep things simple, you can always just spin up a brand new workspace: a warning however is that common user names like `ADMIN` are NOT the same between separate workspaces. There shouldn't be much concern however because apps or workspace users may have the same or different schema access privileges to the database back end.
A Word of Caution to Administrators and Developers:
When you go live with an application or multiple applications on a user-facing system, keep in mind the deployment destination (i.e., the workspace) and what else is sharing that workspace. There are some real situations where apps are not intended to be shared or accessed by other "inside" users. Be sure to read up and understand the security constraints and methods of using Default Apex Authentication security so that it's more than luck that protects your own production/live deployed applications.

I do have the similar requirement, linking from one application page to another.
Tried the above mentioned solution, but still asking to login to second application. My Apex ver is 5.0.3 and trying in same workspace.
Created new authentication schemes for each app with same cookie name and set them as current authentication. Scheme type are Application express accounts.
Setting the link as below from first app page to second.
href="http://servername:port/apex/f?p=224:2:&APP_SESSION"
Could anyone provide a solution, please?

Just an update on this.
I am currently using v21.2 and this is how I do it:
In both applications, go to Shared Components > Authentication Schemes > (Select your Auth Scheme);
Scroll down to Session Sharing and select 'Workspace Sharing';
In one of the applications (source), create a link (as a Navigation Bar List entry, for example) like f?p=173:1:&SESSION., where 173 is the target application ID and 1 is the target page.
After some research, I've found out that this feature (Session Sharing Type) is available since v18 of APEX.

Related

Salesforce: How to automate report extraction as JSON/CSV

I am new to Salesforce, but am an experienced developer. I am provided a link to a Salesforce report, which mostly has the right filters (query). I would like to use an REST API to pull that information as CSV or JSON so that I can do further processing on it.
Here are my questions:
Do I need special permissions to make API calls? What are they?
Do I need to create an "app" with client-key & secret? Does my admin need to grant me permission for this too?
There are a lot of REST APIs from Salesforce, which one do I need to get the info from the report? Analytics?
How do I authenticate in code?
You'd have to work with the System Administrator on the security pieces. Anybody who knows how the company works, can all users see everything, is there Single Sign-On in place, how likely is the report to change...
You will need an user account to pull the data. You need to decide if it'll be some "system account" (you know username and password and have them stored in your app) or can it run for any user in this org. It might not matter much but reports are "fun". If there will be data visibility issues 6 months from now, you'll be asked to make sure the report shows only French data to French users etc... you can make it in report filters or have multiple reports - or you can just use current users access and then it's the sysadmin that has to set the sharing rules right. (would you ever think about packaging what you did and reusing in another SF instance? Making a mobile app out of it? Things like that, they may sound stupid now but will help you decide on best path)
The user (whether it'll be system account or human) needs Profile permissions like "API Enabled" + whatever else you'd need normally ("Run Reports" etc). If you're leaning towards doing it with system user - you might want to look at Password Policies and maybe set password to Never Expires. Now this is bit dangerous so there would be other things you might want to read up about: "API only user" (can't login to website), maybe even locking down the account so it can login only from certain IP ranges or at certain times when the job's supposed to be scheduled...
Connected App and OAUth2 stuff - it's a good idea to create one, yes. Technically you don't have to, you could use SOAP API to call login, get session id... But it's bit weak, OAuth2 would give you more control over security. If you have sandboxes - there's little-known trick. You can make connected app in production (or even totally unrelated Developer Edition) and use client id & secret from it to login to sandboxes. If you create app in sandbox and you refresh it - keys stop working.
(back to security piece - in connected app you can let any user allow/deny access or sysadmin would allow only say these 3 users to connect, "pre-authorize". Could be handy)
Login - there are few REST API ways to login. Depends on your decision. if you have 1 dedicated user you'll probably go with "web server flow". I've added example https://stackoverflow.com/a/56034159/313628 if you don't have a ready SF connection library in your programming language.
If you'll let users login with their own credentials there will be typical OAuth "dance" of going to the target page (Google login, LinkedIn, Twitter...) and back to your app on success. This even works if client has Single Sign-On enabled. Or you could let people type in their username and pass into your app but that's not a great solution.
Pull the actual report already
Once you have session id. Official way would be to use Reporting API, for example https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_get_reportdata.htm
A quick & dirty and officially not supported thing is to mimic what happens when user clicks the report export in UI. Craft a GET request with right cookie and you're golden. See https://stackoverflow.com/a/57745683/313628. No idea if this will work if you went with dedicated account and "API access only" permission.

Use existing user accounts of an existing website

I have a website named satellite.com built by AngularJS+NodeJS+MongoDB, it has an authentication system by ID & password, or third-parties like Google, GitHub. It already has many user accounts.
Now, I want to build a new website named umbrella.com, its authentication system and its database by ReactJS+NodeJS+MongoDB. Umbrella.com will include the functionalities of satellite.com (which will ideally share code with satellite.com) and some other functionalities. In the future, I want both satellite.com and umbrella.com to exist and work (though satellite.com may systematically redirect to umbrella.com/satellite/).
I wonder how umbrella.com can use the existing user accounts of satellite.com. Ideally, I hope
existing users of satellite.com could sign in umbrella.com with their old credentials, and have access to their data of satellite.com
new users could sign up on satellite.com, which will be valid to umbrella.com too
new users could sign up on umbrella.com, which will be valid to satellite.com too
I have total control of the two websites. Does anyone have a clear suggestion on how to structure and share the authentication system and the database of these 2 websites?
Edit 1: one issue is that when I set up Google Authentication for satellite.com, I remember that the domain name (i.e., satellite.com) was required. So now, can we use these authentications for another domain name (i.e., umbrella.com)?
If you are not using third party authentication like Google Auth or something where you have to specifically register your domain you can achieve that by following steps:
You can keep one database structure for both website with different
front-end. For that you user can login to both websites using same
credentials.
You can also go with one backend (Node server) for both the websites
as its seems like both are same and having same functionality.
Front-end can be different.

Empty GUID error when using Azure AD consent flow

I'm currently trying to integrate with Azure AD using the admin consent flow.
I've set up an app in our domain, set a few permissions on it and am then navigating to the following link:
https://login.microsoftonline.com/mytestdomain.onmicrosoft.com/oauth2/authorize?client_id=12345678-1234-1234-1234-123456789012&response_type=code&redirect_uri=http://example.com/responsehandler&resource=12345678-1234-1234-1234-123456789012&prompt=admin_consent&state=12345
(Some of the values here have been swapped out for "example" values)
When I navigate there I get asked to sign in, which I do using a different test domain into which I want to import the app.
After signing in I'm shown a list of all the permissions that the app needs (which appear to be correct), I click accept but then I get the following error:
AADSTS90002: Requested tenant identifier '00000000-0000-0000-0000-000000000000' is not valid. Tenant identifiers may not be an empty GUID.
I'm not sure where this empty GUID is coming from and after some searching I can't find any reference to what might be causing it.
Daniel Camargo's comment above seems to have done the trick.
When I navigated to the login.microsoftonline.com link I was logging in with the user that created the domain.
If I log in with a test admin user that I created it works as I'd want.
I am not convinced that we had exactly the same problem, given that my case was involving a Cordova application, but I will share my scenario anyway:
I created a trial account for my proof of concept and for that I used my personal Microsoft account that I will call mypersonalaccount#outlook.com.
Thus, mypersonalaccount#outlook.com is now part of 2 directories: the outlook.com and my recently created mypersonalaccount.onmicrosoft.com.
When I was trying to authenticate in my Oauth2 application using mypersonalaccount#outlook.com I got that error. My humble guess is that the error is related to some sort of collision between the 2 accounts.
I later created a user1#mypersonalaccount.onmicrosoft.com and a guest account using my gmail account. Everything worked fine with these ones.
Was having the same problem, and the same after 1 week of work by the azure team, was solved.
My problem was being trying to log in to VSTS with AAD accounts.

ExtJS and page authorization (server-side)

I'm looking for information on how to implement secure pages using ExtJS 4. By secure pages I mean the user will log into our website using Siteminder (SSO) and so we will have the user's identity. Then we would determine what roles the user would have by making a database/LDAP call and only render those views/components that the user has access to.
Several questions come to mind:
1.) Of course I would expect we would do the authorization check prior to rendering the pages on the server-side, so how do you do this prior to firing Ext.onReady()? I need to have the ExtJS wait for the response from the server?
2.) What is the best way to organize a page's components where the case may be someone could see a particular component and another person cannot?
3.) How do I deliver the resulting page (i.e., the pieces the user has access to) to the client?
TIA!
If you're working from a Java background and are comfortable using Spring, I wrote up an approach using Spring Security here. This will allow you to plug-in any authentication mechanism you want. The main difference is that instead of using an index.html to bootstrap the application, I have a JSP so that the Spring Servlet Filter will fire for authentication. The Ext JS app blocks until the user is authenticated and the user's roles/permissions are provided.
Use a server side technology to pre-process authorization by putting your JS App launch script into a JSP/GSP. What this does is forces server side components to kick off first and then render the HTML/JS/CSS to the client. For full RIA app use index.gsp(or jsp) and the your URL stays "domain/contextroot" .
You can interrogate access privs to content via ajax request to server or alternatively you could set JS variables via again JSP technology that is processed first before the rest of the client response is returned.
< g:javascript>
//global env var definition
var env = "${System.getProperty(Environment.KEY)}";
< /g:javascript>
Both of these are not 100% safe as client side code can be altered. The real security enforcement must be handled on server side when data is submitted for processing.
'3. Easy way would be to hide/show views etc based on 2. above. There are also some experimentation out there with modularizing the client side MVC application by lazy(manually) initializing controllers that may or may not be needed.
Hope this helps.
DB :)
I am currently experimenting with the following solution. Although it will only work for apps with a rather simple set of users, it could be of some help to you.
To begin with, user authentication is done without extjs, using a simple HTML/CSS page. Once the user logs in, its details (user id, role) are saved into the PHP session. And then the page redirects to one of two extjs apps.
One app for normal users (I'll call them clients), these are people who's client side JS does not include any admin functionality. The other app is for admins.
Both apps have their classes inherit from base classes. So we have, for example, base.mainMenu from which both admin.mainMenu and clients.mainMenu inherit. The only difference in the app.js script is the controllers loaded, and per extJS 4 dynamic loading module, only the related views are loaded (ie, seen on the client side). In my case, all pages load dynamically anyway, so my users can only dynamically load pages in their mainmenu.
The admin app blocks certain features using a global JS variable that includes the user's role. So for example, the hiding of an 'edit' button from moderators (an admin group with less rights) is done once the view is loaded (in practice this is actually done by not loading a plugin that allows editing on the view).
To wrap it all up, any call to the server checks whether the session user has rights for the requested operation, so regardless of client side scripts, server operation can only be performed by people with the appropriate rights.
To summarise, you have 3 different strategies that you can mix-and-match:
Loading different apps for different users. If your classes all inherent from base classes, this is easier than maintaining 2 or more completely different apps.
Using a global JS variable to disable/enable certain features for certain users. This is only good if you don't have a problem with the client side loading features that are then disabled (but still seen by debuggers).
Regardless of anything, all server-side calls are checked against session variable.
check out Role-based access control. I use Yii's database-based RBAC, and have a php script that returns the rbac rules in json format when ext starts up
on the client, the best bet is to simply hide or disable functionality that is not allowed.
on the server, you should throw a 403 http error if the user is not allowed to perform a function. handle ajax exceptions in ext and check for 403s.

Get input email address from ACS when using LiveID

Is it in any way possible to wire up an ACS rule to return/PassThrough the user's email adress from ACS using $(InputValue) when using Live ID?
I am using Passive authentication and get redirected out to Live ID but I was wondering if there is any way to wire up a rule from ACS that might get the InputValue email address
From what I can see I think this might be possible by hosting a login page of course but I would prefer to be able to get it in some other way from ACS if possible.
(I should have added that the current scenario is to implement Live ID authentication on top of an existing ASP.Net application with a database backend for user identity and roles.)
Extra information related to the current scenario : The current scenario is an EXISTING system with its own home-grown database authentication security model. I tried all sorts of ways to see if I could intercept the user's email address and eventually decided the available approaches for doing this were not desirable (in this specific scenario).
The only suitable and secure pattern found to transition to Live ID authentication in this scenarioo is to build a Registration system around your application which allows an existing user to register their LiveID and then bring them back to your application to capture their Live ID 'nameidentifier'.
However, given that any unknown user could do this it would be necessary to have an interim authentication step via email or some-such mechanism to validate the Live ID email address being used.
I hope this is of help to someone.
Possible but it requires a bit of code for a custom sts:
https://gist.github.com/1867792
Code doesn't build and dependencies aren't included... but it's largely based off an early thinktecture starter site ported to MVC4 with changes shown above.
Unfortunately it is not possible to get any identifiable claims when using ACS with Windows Live. This is due to Windows Live user privacy policy.
With windows live you will only get a ID claim which is unique to your Relying Party application.

Resources