I have a requirement to retrieve the Auth Code from SalesForce API. I have created the scenario in Postman as below.
Configuring the new Token using the below parameters
Once I press "Get New Access Token", Postman opens a popup and asks to type the Username and Password in the login prompt. It shows the login page to SalesForce.
Once login success, Postman asks to use the token and it will be added here(See below image)
Then I hit the endpoint with the JSON body as a POST request.
I need to recreate this scenario in NodeJS in order to work the whole process as a single process bypassing all the login prompts.
I am using the below method to initiate this task in order to get the Token. However, the resources I found didn't match my requirement.
As the first step, I used salesforce-oauth2 npm package as below.
oauth2 = require('salesforce-oauth2');
var callbackUrl = "https://test.salesforce.com/services/oauth2/success",
consumerKey = "3MVG9sLbBx**********************2Qi.v***Vlhg3",
consumerSecret = "3MV**bBx**********************2Qi.v***Vlhg3";
var uri = oauth2.getAuthorizationUrl({
redirect_uri: callbackUrl,
client_id: consumerKey,
scope: 'api', // 'id api web refresh_token'
// You can change loginUrl to connect to sandbox or prerelease env.
//base_url: 'https://test.my.salesforce.com'
});
return response.redirect(uri);
When I debug I above code, it returns a URL pointing to the login page. I didn't want to pass this step since my requirement is to get the Auth-Code without opening any intermediate authentication popups.
How can I proceed with this? Any idea to program until the 3rd step to get the Auth Token from the SalesForce API?
Thanks in advance.
You tagged this salesforce-communities. It matters, is it really for community ("experience cloud") users or internals? Salesforce has lots of OAuth2 flows to chose from: https://help.salesforce.com/articleView?id=sf.remoteaccess_oauth_flows.htm&type=5
If you know the password and it's internal user (maybe real human, maybe you have some dedicated "Integration User") - you can work with Username-Password flow. There's no login page and no OAuth consent step. But
This flow doesn’t support scopes or refresh tokens. Experience Cloud
sites don’t support the OAuth 2.0 username-password flow.
You might be able to use JWT Flow. You need username (no password) and your Node app would be sending a message signed with certificate that you uploaded earlier to SF "connected app". You could even mark the users as preauthorised so there's no consent screen.
Other than that I think all OAuth2 flows available for community need a human to actually type the password in. You can pass login hint in the url to save them the username but pass they need to provide on SF login page before coming back to your app.
Dig a bit in help, happy to be proven wrong.
Related
I am using Microsoft azure ad a authentication. When I am trying to change the user password with graph api it will give me an error
I have also set permission that is required for password change, but then it will also not work
I have wrote code in node.js with like this
const changePassword = {
currentPassword: ctx.request.body.currentPassword,
newPassword: ctx.request.body.newPassword
};
const client = createAuthenticated.createAuthenticatedClient();
await client.api('/me/changePassword').post(changePassword);
The changing password api can only support delegate permission, it has been indicated in api document, and it also appeared in your error message.
Delegate api permission means you can't use client credential flow to generate access token/credential to call this api, you can only use such as ropc flow or auth code flow to generate the access token.
I think you've read this sample to call the api, but you didn't choose a correct authentication provider. If your app is a website which required user to sign in, then you may choose this one. But pls note, the client-credential-flow is not suitable for this scenario.
=======================Update====================
The html+js code in my this answer provides a sample which integrate msal to let user sign in and generate access token for calling graph api.
Change AzureMgmtScops value to scopes:["Directory.AccessAsUser.All"] then it will return you an access token with this permission, then pls use this token to send a post request like this, I think you can then finish your task. But this way will not change your server side, it's suitable for the structure which is frontend-backend separated.
In my Angular application (Frontend) the users can sign-in as following:
The user will fill-up a login-form (username or email / password).
The user will click on Login and that will hit this endpoint: http://localhost:8080/auth/realms/REALM_NAME/protocol/openid-connect/token
The user will have an answer in JWT format and will get his access_token (jwt token), refresh_token... etc.
Now this token will be used to access my backend APIs that will check the validity of the signature of this token against the JWKs_URI (with the encryption RSA256).
The question now is : how can I enable user registration in the same way, which means, I wish that the user can:
Fill up a registration form
Enter his email, password, password confirmation, more info (attributes maybe)
The user will then click on Register and it will hit an endpoint in Keycloak (/register maybe) which will return some answer about the success of this registration.
BTW: I don't want to use the user management API.
You can use Keycloak Admin REST API to register new users. Make sure to not expose it carelessly.
Regarding you question, related to the authentication, you can register a Keycloak OIDC client. OIDC offers a bunch of resources you can use.
If you register your application as a Keycloak client that uses OIDC direct grant. Basically "direct grant" implies you can get an access token with just a simple POST to /realms/{realm-name}/protocol/openid-connect/token.
The documentation about direct grants is scattered across the Keycloak documentation and some details can only be found in the OIDC RFCs; so I found you this page that ties everything together.
Careful again ! It might be obvious but don't turn you Angular app into a OIDC client otherwise hacker will steal your Keycloak client's credentials. Make sure to have your Angular app call some server, where you'll implement the necessary safety mechanism to block abusive use of your client (for instance using CAPTCHA).
I'm using a Express Nodejs backend + React frontend set up and tried to implement a "Register / Signin with Google" function, but I do not understand what to store in the database after the user is authenticated. In the ordinary register with email approach, I send the email + password to the backend when I register and check if both the email & password match when the user login.
However, I don't know what to store in the db if one is registered with Google. I have already implement part of the google auth with google by following this tutorial in the frontend side, here's my code:
import * as queryString from 'query-string';
const stringifiedParams = queryString.stringify({
client_id: 'MY_CLIENT_ID'
redirect_uri: 'http://localhost:8000/protected_home',
scope: [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'
].join(' '), // space seperated string
response_type: 'code',
access_type: 'offline',
prompt: 'consent'
});
const googleLoginUrl = `https://accounts.google.com/o/oauth2/v2/auth?${stringifiedParams}`;
return (
<a href={googleLoginUrl}>Login with Google</a>
)
But then what's next? I've successfully pass through the auth process and redirected back to the protected_home page. But this only means that this user is a google user, what kind of information should I store their information in backend so that it indicated that the user has registered an account in my backend with this google account?
Also, is is possible to move the logic above to backend? Since google will redirect back to my redirect_urilike this http://localhost:8000/protected_home?code=CODE_IS_HERE, I need to browser to extract the information in CODE_IS_HERE. So it seems impossible to move the login logic to backend, any solution?
What you need to save is user's unique id, his email or phone, and some other user data for your project.
This is just to know if the user already registered or to know the current user in backend.
From backend, you can just set a middleware to verify the token assigned from google.
Then you will get the user's id and you can find a user from your database, if exists, the user is authenticated.
Signin with google.
Get redirected with CODE
Send CODE to backend
Backend will get user id and email with the CODE using google api.
Save user and generate token.
Send the token back to your frontend.
Then the login or signup process is finished.
Basically you should not write it from scratch as there are libraries that deal with Oauth2: PassportJS, openid-client, Grant, OAuth2-client-js. Those should handle all the below steps except storing actual details in your own database.
In general there are some basic steps when implementing third party oauth2 authentication:
Understand well how Oauth2 works https://www.rfc-editor.org/rfc/rfc6749
Redirect to your server from client (react)
Request authorization by redirecting to Google
Get authorization code which will be added to a url in a redirect from google back to your server
Exchange code for an access token (POST)
Use access token to get user profile details from Google (POST)
Save user details if they do not exist yet in your database - in theory you could skip this part
Create session/token and send it back to client (React) - it is another redirect.
You could also not store any user details on your server and just pass back the token obtained from Google to your React app (client), but then you'd need to check if it is valid on every request to your server. Which is why it is simpler to create your own session token and send it to the client.
There are more details as this is quite a topic to start with but RFC6749 should fill in the gaps.
I'm trying to wrap my head around oauth with a React Native app and a separate NodeJS/Express API backend. I understand https://github.com/adamjmcgrath/react-native-simple-auth offers authentication for a React Native app and http://passportjs.org/ offers authentication for a NodeJS backend. I'm unsure how to connect these two for authentication for login and access to the API.
I'd like users to login to the React Native app either by email and password or via Facebook/Twitter/Google. Once logged into the app, what do I send to the API to make sure they are authenticated and have access to a specific route?
Here is an example flow to login and see the logged-in user's settings:
User logs into React Native app via email/password or Facebook/Twitter/Google.
User is authenticated
App makes request to GET /api/settings
API verifies user is authenticated and returns that user's settings or API verifies user is not authenticated and returns a 403.
There's a whole lot to this question, so much so that it wouldn't all fit in a single SO answer, but here's some tips and a general outline that should broadly fit into what you want to accomplish.
OAuth2 Authorization
From the sounds of it, you are interested in using OAuth 2 to provide social login authorization, and would like to do first-party authentication as an alternative with an email and password. For social logins you will end up using the OAuth 2 Implicit flow to retrieve an access token, which is a widely recognized pattern. Because you are also looking to authenticate users with an email and password, you may want to familiarize yourself with OpenID Connect, which is an extension of OAuth 2 and which explicitly supports authentication in addition to authorization.
In either case, once your user has either submitted an email/password combo or granted permission through the social identity providers, you will receive in response an access token and (optionally) an ID token. The tokens, likely a JWT (JSON Web Token, see jwt.io) will come across as a base64 encoded string that you can decode to inspect the results of the JWT, which will include things like the ID of the user and other details like email address, name, etc.
For more info on the different types of flows, see this excellent overview on Digital Ocean.
Using Tokens for API Authentication
Now that you have an access token, you can pass it along with all requests to your API to demonstrate that you have properly authenticated. You'll do this by passing along the access token in your HTTP headers, specifically the Authorization header, prefacing your base64-encoded access token (what you originally received in response to your authorization request) with Bearer . So the header looks something like this:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJh...
On your API's side, you will receive that token, decode it, and then verify the ID and claims in it. Passed as part of the token in the sub property will be the subject, or ID of the user making the request. This is how you identify access and start to do things on your API side with the respective user's rights, perms, etc. It is also important that you validate the access token once you receive it on your API side, to ensure it wasn't spoofed or hand-crafted.
How it looks in RN for Implicit flows
Here's what the general process looks like in React Native for OAuth 2 Implicit flows, which is what you'll use for social identity providers:
User taps one of your social login buttons on React Native UI
Your code that responds to the buttons will build a request URL to those providers, depending on what each wants (because it differs slightly).
Using the Linking API in RN, you will open up that URL in a browser on the device which sends the user off to the social provider for them to do the login/authorization dance.
Once complete, the social provider will redirect the user to a URL you provider. On a mobile device, you will use your own custom URL scheme to move the user from the web view to your app. This scheme is something you register as part of your app, such as my-awesome-app://, and the redirect URL you pass to the social provider could look like my-awesome-app://auth_complete/. See the Linking API docs for how to configure these URL schemes and deep linking.
In the handler for that new URL scheme/deep link, you'll get the tokens passed as part of the URL. Either by hand or using a library, parse out the tokens from the URL and store them in your app. It's at this point that you can start inspecting them as JWTs, and pass them along in the HTTP headers for API access.
How it looks in RN for Resource Owner Password Grant flows
You have the option for your email/password combo for your own accounts of either sticking with the Implicit flow, or switching to the Resource Owner Password Grant flow if your API and app are trusted by each other, meaning that you are making both the app and the API. I prefer the ROPG flow on mobile apps where possible because the UX is much nicer--you don't have to open up a separate web view, you just have them type in their email and password into UI elements directly in the app. So that being said, here's what it looks like:
User taps the email/password combo login button, and RN responds with a UI that includes TextInputs for the email and password
Build a POST request to your authorization server (which may be your API, or may be a separate server) that includes the properly crafted URL and body details that passes along the email and password. Fire this request.
The auth server will respond with the associated tokens in the response body. At this point you can do the same thing previously done in step 5 above, where you store the tokens for later use in API requests and inspect them for relevant user information.
As you can see, the ROPG is more straightforward, but should only be used in highly trusted scenarios.
At the API
On the API side, you inspect for the token in the Authorization header, and as mentioned previously, and if found you assume that the user has been authenticated. It is still good security practice to valid and verify the token and user permissions. If there is no token sent with the request, or if the token sent has expired, then you reject the request.
There's certainly a ton to it, but that provides a general outline.
I am working on a REST API backend service for an app that uses both email and facebook login. Lets just pretend this app is a todo list app and a user can sign in and add notes which they could later view on may different devices.
The "Login with email" is pretty simple, the app would make a request to:
URL: /v1/login
Params: email, password
Then the serivce returns an access token if all this information is correct so we know the identity of the user creating, updating or deleting a note/list item.
Now for the facebook side. I've seen several differnet answers all over StackOverflow and Facebook's documentation. Some people say, just pass in the id and login the user with the matching id. This would mean calling the login function from the Facebook SDK and just keeping that id to send in a request.
URL: /v1/login/facebook
Params: id
That would work but seems highly unsecure. Anyone could get someone else's Facebook id and just send a request to the server. Facebook's documentation mentions also using the account email. We'll what if the user ever changes their email on Facebook, they could never login to this app again. Another hint of security would be passing in the token from Facebook every time. Since those tokens can change or expire, there really wouldn't be a way login past the expiration date.
The final method I know of would be passing in the app secret:
URL: /v1/login/facebook
Params: id, secret
This seems by far the most secure, if you are using https to connect to the server. The downside to this method is, what if the Facebook secret token is ever reset? I mean you could always make a call to the server to request and check if token was reset and if so pass back the new one. But then if anyone had access to the endpoint to check out of date tokens, it could give them the new secret token.
I know we are dealing with the internet here and there will always be security flaws and there isn't a perfect way to do this. But what is the best way?
Try to send facebook_token for that user.
URL: /v1/login/facebook
Params: facebook_token
and service side make a service call to facebook graph api to get information about that user using facebook_token.
get the facebook id from that response and use it to provide data to that user.