Facebook : URL blocked This redirect failed because the redirect URI is not white-listed in the app's client OAuth settings - node.js

Recently I have used Facebook Login option in my website. I have wrote all the APIs needed and tested them thoroughly in using "localhost" as domain. While configuring settings in my APP in Facebook developers account, I have setup all the necessary settings like giving Oauth redirect URL, adding domain name in basic settings and other things. Everything worked fine then. So, I have requested required app permissions like pages_manage_posts, pages_read_enagagment, pages_show_list and applied for them. Facebook approved them in the app review.
the Redirect URL ("https://execute.app/#/socialmedia/management/") that I used in Facebook is correctly put in the Facebook Oauth redirect URL path as shown in the pic below.
I have used server side APIs for Facebook login and graph APIs. I have used Oauth2 for Facebook login. You can see the code below
var OAuth2 = require('oauth').OAuth2;
var oauth2 = new OAuth2(CONSTANTS.FB_APP_Key,
CONSTANTS.FB_APP_Secret,
"", "https://www.facebook.com/dialog/oauth",
"https://graph.facebook.com/oauth/access_token",
null);
app.get('/api/document/facebook/auth', function (req, res) {
var redirect_uri = "https://execute.app/#/socialmedia/management/";
console.log("redirect_uri ", redirect_uri);
var params = { 'redirect_uri': redirect_uri, 'scope': 'email,public_profile,pages_manage_posts,pages_show_list,pages_read_engagement' };
var authUrl = oauth2.getAuthorizeUrl(params);
res.send({
"status": true,
"message": "login url generated successfully",
"url": authUrl
});
});
I will explain the problem in two scenarios below.
Scenario-1: When there is and existing active Facebook session in browser i.e, when some user is already logged into Facebook in facebook.com or developers.facebook.com and when we try to login into Facebook from our website, Oauth Authentication API gets called and returns Facebook login URL with status code 200 and the url gets opened in a new tab, its works fine, we don't need to enter Facebook login credentials again, we can just click on "**Continue as USER**" button and then we get the login code, with which we can get user access token. After getting token everything works as planned.
Scenario-2: But if no user is already logged into Facebook in browser and when I click on **login to Facebook** button, API call is made and it returns login URL, but the response status code sent by Oauth login API is 304. A new Facebook login tab is opened, but there is a warning displaying a message saying "URL blocked.
This redirect failed because the redirect URI is not white-listed in the app's client OAuth settings. Make sure that the client and web OAuth logins are on and add all your app domains as valid OAuth redirect URIs."
But you can see that I have added correct Redirect URL in Facebook already. It works in scenario-1 and does not work in another as I mentioned above.
Note: the Facebook login URL returned by Oauth Authentication API is same regardless the status code 200 or 304 . It goes as " https://www.facebook.com/dialog/oauth?redirect_uri=https%3A%2F%2Fexecute.app%2F%23%2Fsocialmedia%2Fmanagement%2F&scope=email%2Cpublic_profile%2Cpages_manage_posts%2Cpages_show_list%2Cpages_read_engagement&client_id=88XXXXXXX663"
Please help me in solving this issue ,thanks in advance

The OAuth RFC states for the redirect URI that:
The endpoint URI MUST NOT include a fragment component.
It might be a bug in Facebook that it works for some scenarios and does not work for others, but in fact it's best to avoid a URI with a fragment component. If Facebook's documentation states that you can use redirect URIs with fragments I would try to contact them ask why this doesn't work in some scenarios.

Related

Replicate Postman Oauth 2.0 using Python

I have this Authorization request that works.
How can I replicate it in Python?
I am using an Azure AD to authenticate the access.
Since you are working with python, your case is a : Oauth2 login for SSR web applications with Microsoft
Goal
Get an access_token from interactive login using the oauth2 authorization code grant
Steps
Here I will list all the steps required to do it with any language
Create a web with session with at least these endpoints
/ : home page
/callback : server route or path able to receive query params like /callback?code=123456. This along with your base domain will be called redirect_uri. Sample : http://localhost:8080/callback or http://acme.com/callback
Create and configure an app in Azure Dev Console. Same process is in Google, Facebook, Linkedin, etc. As a result you should have a clientId, clientSecret and a redirect url
Create a simple web with classic session in which if user is not logged-in, redirect (302) to this url:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=foo&response_type=code&redirect_uri=foo&response_mode=query&scope=offline_access%20user.read%20mail.read
clientid and redirect_uri are important here and should be the same of previous step
After that, browser should redirect the user to the platform login
If user enters valid credentials and accepts the consent warning, Microsoft will perform another redirect (302) to the provided redirect_uri but with special value: The auth code
http://acme.com/callback?code=123456798
In the backend of /callback get the code and send it to this new endpoint
Add a client_id & client_secret parameters
Add a code parameter with the code sent by microsoft
Add a redirect_uri parameter with previously used and registered on azure. Sample http://acme.com/callback or http://localhost:8080/callback
Add a grant_type parameter with a value of authorization_code
Issue the HTTP POST request with content-type: application/x-www-form-urlencoded
You should get a response with the precious access_token:
{
token_type: 'Bearer',
scope: 'Mail.Read User.Read profile openid email',
expires_in: 5020,
ext_expires_in: 5020,
access_token: 'eyJ0oVlKhZHsvMhRydQ',
refresh_token: 's_Rcrqf6xMaWcPHJxRFwCQFkL_qUYqBLM71UN6'
}
You could do with this token, whatever you configured in azure. Sample: If you want to access to user calendar, profile, etc on behalf of the user, you should have registered this in the azure console. So the clientid is related to that and human user will be prompted with something like this
Libraries
There is some libraries provided by microsoft (c#, nodejs) which will save you a little work. Anyway the previous explanation are very detailed.
Advice
Read about oauth2 spec: https://oauth.net/2/
Read about oauth2 authorization code flow login before the implementation with python
https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
https://auth0.com/docs/get-started/authentication-and-authorization-flow/authorization-code-flow
https://github.com/msusdev/microsoft_identity_platform_dev/blob/main/presentations/auth_users_msalnet.md
Check this to understand how configure the azure web console: https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
Check my gist https://gist.github.com/jrichardsz/5b8ba730978fce7a7c585007d3fd06b4

Nodejs How to bypass the limitation of redirecting without data regarding external auth method?

I have a NodeJS application where I let my users to login via an external auth like Github and Google.
In the frontend I open for the client a tab in Github for example which prompts him to authorize GitHub against my application. I also do this with a callback url. Github then redirects the user back to the callback url I've configured.
Currently this callback URL is an API in my server.
The next step is to redirect the user back to my home page. However, I need to provide the user with some credentials like JWT token.
But I'm limited to send some data along with redirection action. What should I do?
I provide the following data with Github:
super({
clientID: configService.get('githubOAuthClientId', { infer: true }),
clientSecret: configService.get('githubOAuthClientSecret', { infer: true }),
callbackURL: configService.get('githubOAuthRedirectUri', { infer: true }),
scope: ['user:email'],
});
The githubOAuthRedirectUri variable holds my backend api route. Then I handle the data I receive from GitHub in this route controller. Now I want to redirect the user back to the home page but he also needs the JWT token and some more user specific data.
After receiving data from Github, you could redirect to an intermediate page, sending data in url query for example, and then the front-end app redirect to the home page.
That's my idea
I assume that the OAuth provider (Google or GitHub) will invoke your callback URL with an authorization code in a URL parameter ?code=.... Your server must then exchange this authorization code for an access token by making a token request to the OAuth provider. The response to that token request will then contain the access token, which is
either a JWT with a sub claim containing (most likely) the user's email address, see https://stackoverflow.com/a/72590693/16462950
or an "opaque" token, which your server must use in an Authorization: Bearer header of a UserInfo request.
Only after these steps do you know who the user is. Your server could put the JWT in a session cookie so that it is sent again (and must be validated again) in all subsequent requests.
If your server receives an opaque token instead of a JWT, this may be only short-lived and hence cannot be used in a session cookie. In this case, your server could construct its own JWT containing the user info.

Getting access token using Auth code flow in Outlook web add-in

After all my research and reading Microsoft docs, am unable to conclude how to generate access token using auth code flow in outlook web add-ins. I can successfully generate access token using implicit grant flow with the help of Dialog API which simply opens up URL and we read access token from address bar.
To be more secured , I am trying to generate access token to graph API/(custom SharePoint sites) using registered app in azure utilizing auth code flow.
Azure app Settings:
API permissions added under Microsoft Graph. [User.Read, Sites.Read.All]
Redirect Web URI: myapp/Auth_Result
Redirect SPA URI: myapp/Auth_Result_SPA
Code in Outlook Web add-in:
Using Dialog API I open myapp/Auth page which redirects to
https://login.microsoftonline.com/<Tenant ID>/oauth2/v2.0/authorize
?client_id=<Client ID>
&response_type=code
&redirect_uri=https%3A%2F%2Flocalhost%3A44333%2FAuth_result.html
&response_mode=query&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
&state=12345
The above URL generates Authorization code in redirected page myapp/Auth_result which is read.
Code in Auth_Result page
function GetAccessToken(authCode) {
try {
var url = 'https://login.microsoftonline.com/<Tenant ID>/oauth2/v2.0/token';
var params = 'client_id=<Client ID>&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read&code=' + authCode + '&redirect_uri=https://localhost:44333/Auth_Result_SPA.html&grant_type=authorization_code';
var xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function (result) {
AccessTokenCallback(result);
}
xhr.send(params);
}
catch{ }
}
The above request fails with
Access to XMLHttpRequest at 'https://login.microsoftonline.com/<Tenant ID>/oauth2/v2.0/token' from origin 'https://localhost:44333' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
MessageRead.js:780 POST https://login.microsoftonline.com/<Tenant ID>/oauth2/v2.0/token net::ERR_FAILED
App domains in Manifest
<AppDomain>https://login.microsoftonline.com/<Tenant ID>/oauth2/v2.0/token</AppDomain>
<AppDomain>https://login.microsoftonline.com</AppDomain>
<AppDomain>https://localhost:44333</AppDomain>
<AppDomain>https://localhost:44333/Auth</AppDomain>
<AppDomain>https://localhost:44333/Auth_Result</AppDomain>
<AppDomain>https://localhost:44333/Auth_Result_SPA</AppDomain>
<AppDomain>https://graph.microsoft.com</AppDomain>
I am not sure what am I missing? Now I am questioning is it even possible to use auth code flow in outlook web add-in?
Guys any suggestions would be helpful.
Thanks
------Edited-------------
I tried above solution with redirect URI as Web platform.
If I use SPA platform redirect URI in azure app Authentication then I get following error:
For some reason image is not coming up.
Error Text:
AADSTS9002325: Proof Key for Code Exchange is required for cross-origin authorization code redemption.
[![enter image description here][1]][1]
Looks like the immediate problem is that your Azure AD client needs to be a Single Page App as in step 6 of my post, so that you get past the CORS error.
DESKTOP FLOW?
I believe you are operating within the context of a desktop app (Outlook). If so then the official OAuth option would be to use the following ingredients:
Authorization Code Flow (PKCE)
Use the system browser to login
Listen for the response on a loopback url, such as http://localhost:8000
See my Desktop Tutorial + Code Sample for an example of this
Thanks for your replies, I managed to generate access token using auth code flow. It turned out I wasn't providing code challenge and did not fully understood the flow of authentication particularly for Outlook web add-ins.
The solution is here.
Requirement to make this solution work.
Replace: <Tenant ID> = your tenant id from Azure App registration
Replace: <Client ID> = your client id from Azure App registration
Set https://localhost:44300/Auth_Result_SPA as your redirect URI in Authentication-> SPA platform.
Set Scope to your requirement, and make sure you add the scope in API permissions after registering you application in Azure.
Make sure the app url matches when you load project in visual studio.
app url = SSL URL in TestGraphWeb project properties
Refernces:
Refer this to generate code challenge and code verifier
Refer this for auth code flow information.
This is sample Outlook web add-in with Application Name as "TestGraph". When app is loaded in task pane it will generate access token using Auth code flow silently. This app will pop up dialog if user action is required to generate authentication code. After generating access token it will load page with only button "Refresh Access Token" which will generate new access token and refresh token.

AAD app registration not accepting the query string parameter

I have registered the app in Azure AAD with reply urls. Enable id_token and auth token. If i give the exact url as the parameter it works fine. but if I add the query string as a parameter in reply url it is not working and throws error
AADSTS50011: The reply url specified in the request does not match the
reply urls configured for the application: ''.
Below is my sample URL format generated by ADAL.js file.
https://login.microsoftonline.com/.onmicrosoft.com/oauth2/authorize
?response_type=id_token &client_id=
&redirect_uri=?p1=123&p2=456
&state=62439108-d296-4a0d-91cc-4f6580656e83
&client-request-id=1a5ad90a-26fc-4e60-bbcc-8d58bbbcc1f7
&x-client-SKU=Js &x-client-Ver=1.0.13
&nonce=a4a6215c-0706-4fbc-91a9-36e4cd3a262e
If i remove this ?p1=123&p2=456 query string from the redirect_url, it works fine. The other workaround i see is if i go to legacy app registration and add "" at the end of the url it is working. But the new app registration does not allow "" in the reply_url while registration.
Anyone else also faced the same issue and fixed without adding "*" in the reply_url registration? please let me know.
This is an issue with ADAL.js (and MSAL.js) setting the redirect URI to the current URL by default.
You can get around it with an approach like this:
Set redirect URI as window.location.origin + "/aad-callback" (or anything else)
When requiring login, store current URL in sessionStorage (or local storage or a cookie)
Trigger login redirect
When your app gets a callback to /aad-callback, handle the tokens from the URL fragment
Load the local redirect URL from sessionStorage
Redirect user there
I wrote an article related to this but for MSAL.js: https://joonasw.net/view/avoiding-wildcard-reply-urls-with-msal-js.
The concepts are the same for ADAL.js.

How to enable server side offline access for Chrome Extension OAuth?

I am working on a Chrome extension where the backend server requires offline access and a refresh token for the user's account. I am not familiar with Chrome extensions, and not sure how I should do the authorization in this case.
The benefit of using chrome.identity is that I can set interactive=false and attempt to authorize without bothering the user when the plugin loads. However, the getAuthToken() method doesn't provide a way for the backend to get a refresh token.
If, instead, I use the launchWebAuthFlow() method and redirect user back to OAuth page, i.e.
chrome.identity.launchWebAuthFlow({
url: https://*<my_host>*/auth/google,
interactive: true,
}, function(url) {
var uri = URI(url),
params = uri.search(true);
var token = params.authToken;
done(token);
});
where https://*<my_host>*/auth/google is my server OAuth path, then for some reason the Permissions scope page doesn't show up. Instead, it shows the Google login page. (Note: if I navigate to https://*<my_host>*/auth/google using the browser, it permissions page shows correctly.)
Is there anyway to do this with chrome.identity API? If not, do I have to do the OAuth using a popup? What's the proper way to do this normally?

Resources