My Salesforce Visualforce page doesn't require authentication [closed] - authentication

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a legacy system that needs some tiny improvements to enable the system to run without interruptions. I got recently a security notification from Salesforce that there are some upcoming changes coming with the Winter ‘21 release that is going to have an effect on my system. The Secure guest user record access is going to start to be compulsory. By turning this setting on as a test prevents my system from working properly right now. The system has currently been set up to use the Visualforce page to access APEX scripts that make some business logic and even update/insert some data to Salesforce. That Visualforce page has been called from another system that runs totally separately. As much as I follow the upcoming Salesforce release makes it impossible to insert/update data in the way I have been currently doing. I realized I need to secure this with some kind of authentication so I can keep my system working when the Secure guest user record access option has been ticked. I want to add a user authentication for my apex script. I created a new Connected App and did the following:
Enabled OAuth Settings
Set OAuth Scopes Full access (full)
Set IP Relaxation to Relax IP restrictions
Exposed Apex Classes as REST Web Services
I have currently been using Salesforce Sandbox as a test. I created a new connected app and made a login call first. That all worked fine and returned me access token. I did make sure that I didn't have any sessions open when I called the apex script via the Visualforce page where I have defined a new apex:page. For some reason, my Visualforce page is always public and allows me access to everything without asking me any token.
After having done all this I can still get access to everything without doing any user authentications.
Can someone please advise me on this.
Here I am calling Visualforce page that in return calls APEX script:
HttpRequestMessage apiRequest = new HttpRequestMessage(HttpMethod.Post, restCallURL);
apiRequest.Headers.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
apiRequest.Headers.Add("Authorization", $"Bearer {authToken}"); //check Bearer
It works fine even without me setting a token to it.
This is how my Visualforce page looks like:
<apex:page controller="TestGatewayResource" sidebar="false" showheader="false" contenttype="text/plain" action="{!action1}">{!StringCodeReturned}</apex:page>
This is my test Apex script:
#RestResource(urlMapping='/test_defined_type/*')
global class TestGatewayResource
{
String StringCodeReturned = ""; // very simplified to give an idea what I am doing.
#HttpPost
global static String activate()
{
// makes some work by calling other classes and inserting/updating data to Salesforce
}
}
Edit: I added more background information to understand better my issue. I also added some code samples. Tyi I have no more experience than a week working with Salesforce trying to figure things out.

(too long for a comment)
Your question is confusing, what are you trying to do? Connected apps are for API access (REST, SOAP) but then you write about Visualforce page, that's for normal browser-based access.
As internal user you'll have access to all VF pages (well, if you're sysadmin or your profile has them assigned). No connected apps needed. If you're external user (guest) you can still access a VF page if it was exposed on a Site. No login needed = no OAuth2.
With API access you need to make login call first (few ways to do it, SOAP or there are ~9 OAuth2 options to choose from) and then you'd access apex REST services for example (again, if your profile allows).
If you want to do programmatic screenscraping (pull html of VF pages instead of calling APIs) that's doable too but you need to pass a session id as cookie instead of Authorization header. That's not an officially supported API though.
What are you trying to do? Can you post any code maybe?

Related

Authorization best practices? Where should authorization take place to hide/block pages from the user in nextjs? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 days ago.
Improve this question
I am currently in the process of designing a network of servers and databases for a project.
One key aspect of this project is the implementation of a central authentication server which will utilize session IDs to track sessions. These session IDs will be stored in cookies and sent back to users upon successful login.
Note: I understand that nextjs can work as both a front end and a back end. For reasons I will not get into here, nextjs is being used as a front end, and a separate central authentication server is being used for authentication. There are other servers/databases that will store data that users can access if they have proper permissions levels.
In step 1, I have no questions.
In steps 2 and 3, when the cookie is sent back to the nextjs server, what is the best practice for nextjs to determine the authorization level of the user?
I believe it's important that...
- Nextjs should know what navigation tabs to show, etc., when it renders the page for the user.
- Nextjs should also know what pages the user is allowed to visit. If the user is asking for a server-side rendered page that it isn't allowed to visit, it should be blocked
Possible option: Here, do I include some sort of JWT with authorization levels? It is my understanding that nextjs may be able to read these JWT authorization levels in middleware, then deny certain page requests that the user has by reading the JWT each time they request a page. Perhaps, even without middleware, functions could be used within the pages that would run server-sided, checking the JWT permission levels. Note that, in order for the nextjs server to know what the authentication levels are for the user, the tokens would have to be created in the central auth server, and then sent to the nextjs server.
Side thought: It seems that if I were to implement a function that checks the authorization level on a SPA, there would always be a way that a hacker could at least visit the blank page, correct? In other words, the only way to truly hide pages and navigation tabs from a hacker would be by somehow checking authorization levels server side (server-sided rendering), and then sending back a rendering of the page that only shows items related to the exact permissions of the user?
Overall, I would greatly appreciate any advice or insight on the best methods for authorizing users and limiting access to pages and tabs based on permission levels. While cookies will be used to store the session id and determine the data that users can receive when making API calls, additional measures such as JWT may be necessary for authorizing users to view specific pages. Is it common to utilize a combination of session/cookies and JWT for this purpose? What are the recommended best practices in this scenario?
Thank you for your assistance.

Building an API to send random numbers to my website [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 months ago.
Improve this question
I am trying to make a custom API which uploads random numbers generated to my website page (to learn how API works). And whenever I want to see the page, I use my API key to do so. Can you help me in this? I am new to API stuff.
When creating APIs, there are lots of decisions to make. You could render your structure on the client-side and query your application server via RESTful API calls. Or you could have a server-side rendering approach and use your API internally. There are four main types of APIs:
Partner
Internal
Composite
REST
https://www.techtarget.com/searchapparchitecture/tip/What-are-the-types-of-APIs-and-their-differences
In your scenario it seems that you need to either choose an internal API approach or a RESTful approach.
Your random number function itself would be similar in both cases (a simple function written in the language of your choice).
However, the token usage largely depends on the type of your API.
You need to decide whether you are going to have usernames and passwords and is the purpose of your token only to avoid frequently logging in with very sensitive data, such as username and password, so, you use a token instead, which, if falls into the wrong hands, then they could not steal the identity of your users for good, as they are still not reaching these credentials. If so, then you will need to generate the token periodically. A way to do so is to generate it every week/month (whatever) and somehow send it out to your users. Or it could be generated whenever the user has to log in, sent to the user, who will be able to use that token from there on.
Or, you could separate the token from the login and provide a UI for the user where he/she can generate tokens while being logged in. There are quite many ways to approach this.
Otherwise, if there is no username and password and, there is a token and secret to identify the user, then you will need an alternative to the login. It could be a simple request for token generation. Or it could be a repeatedly generated and sent token.
In any measures, when you intend to run an API function as a user, then you will need to send the information that identifies your user. On most webpages this is handled by getting a session ID (that acts as a token) upon login and then, while the session exists, that session ID is always sent to the webpage, whatever request is being sent, this is how the website knows that you are logged in. Most webservers and programming languages that handle web requests also handle token generation and usage and browsers are in line with these through the cookies, which are small files that contain information for the website.
If you are having a custom environment or you prefer a custom token management, then of course you can implement your own.
But, if you want to achieve simplicity, then you could implement a register and a login feature for your API as well as the number randomizer, so these are 3 API functions for now, call the register when a user registers, store a 1-way-encrypted password, do a validation (like email sending with a token to the user) and implement token-based user validation, which is a fourth API function. So, the user:
registers
receives an email with a token
clicks on a link that has that token as a request parameter
once that page opens, store the user as an authenticated user and remove the registration token
This will enable logging in for your user. Once your user is logged in, a session ID should be generated (in PHP you need to look into the functions whose name start with session_, for example) and then using that session ID your API should make sure that the randomizer can be called and your UI should be designed in such a way that this feature could be found by users.
If I may, I advise you to avoid getting into your own token generation while you are learning, choose the simplest ways and once the simplistic configuration you have chosen is working reliably, then you may choose to write your own token logic if you prefer that for some reason.

How is the access_type=online oauth mode (no refresh token) supposed to work?

This question is has a lot in common to the previous question Google OAuth: can't get refresh token with authorization code (and I won't be offended if it's considered a duplicate) but there are some differences: that question uses the Javascript and PHP libraries, and I'm using neither of those. That question wants to know how to get a refresh token, and I want to know if I should want a refresh token, or how the mode with no refresh tokens is intended to work.
I'm following this guide:
https://developers.google.com/identity/protocols/OAuth2WebServer
The goal is to allow users to upload files from Google Drive to my web application.
I'm not using one of Google's favored programming languages, so I don't have a library abstracting away all the interaction with Google. I need to know what the HTTP requests should actually should look like.
One of the parameters in the authorization request is access_type. The description says
Set the value to offline if your application needs to refresh access tokens when the user is not present at the browser.
I won't need to do that (I'll only want to retrieve a file on my server immediately after the user selects it) so in the spirit of not asking for more privileges than you really need, I used access_type=online. This gives me an access token and no refresh token. I've successfully used the access token to make some requests to Google Drive.
The user comes back the next day and tries to upload another file. While processing this request from the user, I make a request to Google Drive. The access token is expired, so I get a 401. What's supposed to happen next?
My guess is I should pretend this is a completely new user and send them through the full authorization process again. That would mean I have to abort whatever the user was trying to do, redirect them to https://accounts.google.com/o/oauth2/auth with all the parameters (scope, client_id, etc.) and embed enough information in the state parameter that I can resume the original request when the user gets back from their detour.
This seems rather difficult (in particular the part about saving and resuming the state of my application at some arbitrary point). It's a big enough obstacle that it should be explained somewhere. But the description of the access_type parameter didn't say anything about needing to insert authorization redirects everywhere. It just said the user must be "present".
You are using the right implementation. You don't need offline access if you aren't going to make requests when the user is not using the application. The thing is that access tokens expire in 1 hour. So you need to generate new access tokens if a user leaves the application and come back later.
If users have authorized your application, calling this URL with your configuration should return a new valid access token:
https://accounts.google.com/o/oauth2/v2/auth?
scope=scopes&
include_granted_scopes=true&
state=state_parameter_passthrough_value&
redirect_uri=http://oauth2.example.com/callback&
response_type=token&
client_id=client_id

Keycloak - Multi/2FA Factor - OTP - QR Code - Custom Login Screen - Rest API

I have my own Login page where user enters username/password.
This username/password are used to login through Keycloak Rest API.
http://localhost:8080/auth/realms/Demo/protocol/openid-connect/token
input - {username,password,grant_type,client_secret,client_id}
And in response i get access token.
Now i wish to enable Authenticator (Google Authenticator). I have enabled it from backend. Now if user wishes to login thorugh my application, my login page i need to get below details.
1.) Somehow i need to include QR Code that appears on keycloak login page post username/password validation to show on my login screen for the first time login once user enter username/password. So do we have any API which return Keycloak QR code image in response.
2.) Subsequent login i will have OTP field, so need a REST api to pass OTP along with username/password.
Please help with REST API if keycloak has any. Integrating through Javascript.
Similar flow as described in use case 1 here
Just want to use keycloak as a database, doing all operation for me, input will be my screen. I do want redirection of URL's while login in and yet should be standalone deployed.
I've managed to implement this through the rest API of Keycloak. To realize this, you need to extend Keycloak yourself with a SPI. To do this create your own Java project and extend org.keycloak.services.resource.RealmResourceProvider and org.keycloak.services.resource.RealmResourceProviderFactory. You can find more information in the official docs (https://www.keycloak.org/docs/latest/server_development/#_extensions), github examples and other stack overflow posts how to do this.
Once you got this up and running you can implement it like this:
#GET
#Path("your-end-point-to-fetch-the-qr")
#Produces({MediaType.APPLICATION_JSON})
public YourDtoWithSecretAndQr get2FASetup(#PathParam("username") final String username) {
final RealmModel realm = this.session.getContext().getRealm();
final UserModel user = this.session.users().getUserByUsername(username, realm);
final String totpSecret = HmacOTP.generateSecret(20);
final String totpSecretQrCode = TotpUtils.qrCode(totpSecret, realm, user);
return new YourDtoWithSecretAndQr(totpSecret, totpSecretQrCode);
}
#POST
#Path("your-end-point-to-setup-2fa")
#Consumes("application/json")
public void setup2FA(#PathParam("username") final String username, final YourDtoWithData dto) {
final RealmModel realm = this.session.getContext().getRealm();
final UserModel user = this.session.users().getUserByUsername(username, realm);
final OTPCredentialModel otpCredentialModel = OTPCredentialModel.createFromPolicy(realm, dto.getSecret(), dto.getDeviceName());
CredentialHelper.createOTPCredential(this.session, realm, user, dto.getInitialCode(), otpCredentialModel);
}
The secret received with the GET must be send back with the POST. The initial code is the one from your 2FA app (e.g. Google Authenticator). The QR code is a string which can be displayed in an img with src 'data:image/png;base64,' + qrCodeString;
I know this is an old question, but I've recently been looking at something similar, and so thought it would be potentially valuable to share what I have found for others who may be looking into this and wondered what the possibilities are.
TL;DR
You can only really use the existing Keycloak actions to do this or embed the user account management page found at https://{keycloak server URL}/auth/realms/{realm name}/account in an iframe. That's it, I'm afraid. In my opinion it is currently best to just assign actions directly to accounts or use the Credential Reset emails to assign actions; both of these can be done via the Admin API if desired:
Send Credential Reset email containing assigned actions:
https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_executeactionsemail
Set actions directly on the account (include the actions in the requiredActions portion of the user JSON that you send in the body to the endpoint):
https://www.keycloak.org/docs-api/11.0/rest-api/index.html#_updateuser
Background is that as part of a project that I have been working on we wanted to see if we could have an integrated way for users to set up their initial password and OTP device when a new account has been created for them, since the default method of sending them an email from Keycloak using the "Credential Reset" functionality has the limitations that a) it doesn't provide a link to the application itself unless you override the theme, and if you have multiple instances of the application for different users you have no way of knowing which instance to provide the link for, so may have to end up including a list of them, and b) it often doesn't feel truly native to the application, even with changes to the theme. If you're sensible though, I'd suggest you stop and just use this functionality - please see the TL;DR section above for details.
So, in short there is NO API endpoint for receiving a QR code to set up an OTP device. There are two places, however, where the QR code can be retrieved from - the OTP device setup screen when you log in as a user who has had a "Configure OTP" action assigned to their account, and the user's own account management screen.
The first option of the Configure OTP action screen is a non-starter. It only shows up when you log in, and so by definition the user has to log in to Keycloak via the Keycloak login page in order to trigger the page to be displayed. At this point you're already on a Keycloak page instead of one of your app's pages, and so unless you can get very creative with changes to these Keycloak pages via a custom theme, tapping into this page isn't really an option.
The second option is more interesting, but far from ideal. Every user who has logged in has access to an account management page that can be found at https://{keycloak server URL}/auth/realms/{realm name}/account. This page allows you to do things like change your name, password, etc. and it also allows you to add an OTP device if you don't already have one, or delete any existing OTP devices associated with your account. This OTP device tab of the account management page can be reached directly via https://{keycloak server URL}/auth/realms/{realm name}/account/totp.
As I mentioned, there isn't an API that you can access to view the QR code that shows up on this page. The only way it is accessible is via the GET request to https://{keycloak server URL}/auth/realms/{realm name}/account/totp, which returns the HTML for the page I've already mentioned. Okay great, so can we scrape the QR code programmatically and then put it in our own page on our application? Err, no, not really. You see, whilst a lot of the Keycloak API endpoints rightly allow you to send a bearer token (e.g. access token) in the authorization header to access and endpoint, this page will not accept a bearer token as a means of authentication/authorization. Instead it uses a session cookie that is locked down to the Keycloak URL. This cookie is set when you log in to your application via the Keycloak login page, and so is available to this account management page when you navigate to it, having already logged in, and since the account management page uses the same server and domain name as the original Keycloak login page, it has access to the cookie and can let you in. This cookie cannot be sent by your application to e.g. your own REST API to then programmatically call the account management page and scrape the QR code, because your application doesn't have access to it for good security reasons. This might be something you can change in Keycloak somewhere, but if there is I would strongly recommend against changing it.
So if we can't scrape the page from our own server, can we do something on the front-end? Well, as mentioned, your application doesn't have access to the session cookie but if you make a request (e.g. using fetch or axios) in your front-end JavaScript to the account management page then that request will send the cookie along with it, so that could work right? Umm, well actually you will get hit with an error message in this scenario due to CORS. CORS is Cross-Origin-Resource-Sharing and in order to allow the Keycloak page to be accessed then you would have to open up the settings on the server to allow it to be accessed from your website's address. I've seen some articles that look at how you can open up your CORS settings on Keycloak if you wish but I'd be very nervous about doing this. I don't know enough about the internals of Keycloak and how it operates to comment on how much of a security risk this is, but I certainly wouldn't recommend it. There some information here (Keycloak angular No 'Access-Control-Allow-Origin' header is present) on changing the "Web Origins" setting of your application's Keycloak client, but this opens up your application to some serious potential abuse. There is also the MAJOR issue that even if you scraped the QR code, the device isn't actually added to the user's account (even though it appears in the authenticator app) until you enter a code into the page that the QR code is on and click Save. Since there isn't an API endpoint that you can use to complete this operation, I therefore don't think that this option is viable either. I've tried out whether or not you can use the token retrieval endpoint at https://{keycloak server URL}/auth/realms/{realm name}/protocol/openid-connect/token to see if making a request with your username/password/otp code will somehow "register" your device and complete the process, but although you can get a token this way, and it doesn't complain about the otp code, it doesn't actually take any notice of the code because as far as it's concerned the user's account doesn't have a device registered with it. So we have to use the form on the account management page in order to complete this registration process.
So the final way of possibly doing this is.... an iframe. Sorry, yeah it's rubbish but that's all your left with. You can have the iframe point at your account management page, and because the user is logged in then they will be able to see the contents from your application's page. You can use relative positioning, fixed width and height and remove scroll bars to ensure that you ONLY show the QR code and the fields for the one time code, device name, and the Save/Cancel buttons. This, sadly, seems to be the only option at the moment, and due to how nasty and unreliable iframes can be in general - they certainly don't feel native to your application, and you'll need to override your Keycloak theme to get the page in question to look more like your app - I'd recommend steering clear of this and using the standard approach of using Keycloak actions and the Admin API instead.
If you've made it this far, congratulations, you win at Stack Overflow :-)

GWT: Authentication for some part of application using GWT login page

My application has some features that are accessible to all users, and some other features to which access should be restricted to authenticated users only. All these restricted features exists within some set of GWT Places, thus, all Places available in application can be divided into two groups: "accessible for all", and "restricted". In my opinion, places with restricted access, could implement some interface (let's say it would be RestrictedAccess), and if user proceeds to one of them, and it has not been authenticated yet, it will be redirected to the login screen - it's more OO-approach than applying filters basis on URL.
What I'm trying to achieve is:
Information about if user has been
authenticated or not should be
stored on server (it's not something
that could be stored in a cookie...)
Login page is a standard GWT place+view+activity (!)
User name & password validation is done on the server side.
So far, I've introduced RestrictedAccess interface, which is implemented by some set of places. My FilteredActivityMapper.Filter implementation, which is passed to the FilteredActivityMapper wrapping application activity mapper has the following logic:
Place filter(Place place) {
if (place instanceof RestrictedAccess && !userHasBeenAuthenticated()) {
return new LoginPlace();
}
// return the original place - user has been already authenticated or
// place is accesible for all users
return place;
}
private boolean userHasBeenAuthenticated() {
// remote call - how to do ???
}
The problem is with userHasBeenAuthenticated() method (user should not be redirected to the LoginPlace, if it has been already authenticated). If I want to store this information on the server-side, I have to do GWT RPC/request factory call here, but both are asynchronous, so I cannot work on its result in the filter method.
I know that I can use web.xml filters or some external framework (e.g. spring security), but none of this approach allows me to have login page as a standard GWT - based form, or indicating in the more OO way that access to some place should be restricted.
Thanks in advance for any hints
EDIT: I've started to wondering if places filtering (restricted/not restricted) should take place on the client side at all. If, as it was suggested, there is a possibility to hack code indicating if user has been authenticated or not, there is also possibility to hack places filtering code, so that it will be possible to access restricted places without signing in.
Piotrek,
I think there is a security issue with calling userHasBeenAuthenticated() - it would be possible to hack the client side code to return true every time this function is called.
The solution I've implemented is to simply return SC_UNAUTHORIZED if an unauthenticated user attempts to access any remote service. I've overridden the RequestFactory onResponseReceived function which redirects to a login page if the response is SC_UNAUTHORIZED. Idea taken from:
http://code.google.com/p/google-web-toolkit/source/browse/trunk/samples/expenses/src/main/java/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java
This works for our situation where the Activities and Places are all data-centric - each place change retrieves data from the server. If a user isn't authenticated they simply don't get the data and get redirected to a login page.
I realize your situation is slightly different in that some places are accessible to everyone, in which case you could configure only the restricted services to return SC_UNAUTHORIZED.
I have a similar application with the same requirements. As yet I have not got round to to the implementation but I was thinking along the same lines.
What I was planning on doing is storing the authentication state client side in an AuthenticationManager class. When the app starts I was going to request the login info from the server (I was thinking of running on app engine so I would get the authentication state and also get the open id login/logout URLs) and store this in the AuthenticationManager. Acegi/Spring Security works in a simlar way so this info is available server side if you use those too.
When the user logs in/out they will be redirected by the server and the new state will be retrieved. This should keep the client authentication state in line with the server. Each RPC request on the server has to be checked for authentication too. I was using the gwt-dispacth library and this has some rudimentary authentication checking and cross site script protection in in too (although I think latest GWT has this for generic RPC).
One issue is session timeouts. Again the gwt-dispath library has some code that detects this and returns session expired exceptions to the client which can be intercepted and the auth manager updated.
Hope that makes some sense.