The authentication process for O365 requires adding the redirect URL in a whitelist on the app’s dashboard on Azure.
However, this whitelist doesn't work with domain names. It requires to add the entire URL for every page which is not possible if you have a huge number of URLs, plus some of the URLs are dynamically generated by the backend.
Is it possible to whitelist the domain with all its sub-directories/URLs in one go?
No, it is not (unless you want to use wildcards, which you shouldn't).
In general when you need dynamic redirects,
you should store the location you want to redirect to locally in a cookie/session/local storage/session storage.
Then use a single redirect URL, and when you get the redirect there, get that stored "local redirect URL" from where you stored it, and redirect the user there.
I touched upon this on a recent article: https://joonasw.net/view/avoiding-wildcard-reply-urls-with-msal-js
Related
I am using react-onedrive-filepicker to retrieve file content from a selected file located on OneDrive.
My code is like:
<ReactOneDriveFilePicker
clientID={process.env.NEXT_PUBLIC_MICROSOFT_CLIENT_ID}
action="query"
multiSelect={false}
advanced={{
redirectUri: "https://graph.microsoft.com/v1.0/me/"
}}
onSuccess={(result) => {
alert(JSON.stringify(result));
}}
onCancel={(result) => {
alert(JSON.stringify(result));
}}
>
<Button className="btn btn-md btn-primary">MSOneDrive</Button>
</ReactOneDriveFilePicker>
I am actually getting this error
I am at a loss here, because I have no idea what URI is supposed to expect nor how to pass it... I have registered https://login.live.com/oauth20_desktop.srf on my Azure app, but it appears not to be the right address to show a user's OneDrive folder...
Where am I going wrong here?
I have also opened a issue on the react-onedrive-filepicker GitHub, but I am afraid the repo might be unmaintained..
EDIT
I am now passing the redirectUri value for MS Graph to the component, but it claims that redirect uri is not in the same domain as picker sdk... Now, it looks like a never-ending loop:
I cannot put the page URL where the picker is hosted, because it is a dynamic address...
but even if I put there the local URI, what's the point? I won't see the OneDrive files of my user...
What is impressive is how easy it is to make the Google picker work, and how incredibly difficult it is to make the MS work...
TL;DR
Your apps URL should be the path at which you can access your app in the browser. This URL has to be registered as redirect URI both in the Azure client configuration as well as in your ReactOneDriveFilePicker component.
To access Microsoft APIs, there are different steps to follow. First, you have to register your application with Microsoft. Then the user authorizes your application to access their data and only then you are allowed to access the files. Your struggles may actually come from the authorization step. Microsoft uses the OAuth protocol for managing access to their API resources (Docs: Auth and available auth flows), during which the user gets redirected to the Microsoft site, authorizes your app and gets redirected back to your application:
(diagram by ArchitectXChange.com)
Only then, you can access the API resources, in your case the OneDrive files.
The redirect URI now refers to the exact address your file picker is located at. Lets say you are running your application on localhost with the path /onedrive-filepicker, then your redirect URI will be http://localhost/onedrive-filepicker, since this is the place your button is located at. Now you have to put this URL into the app registration with Azure, so that Azure makes sure no one is kidding around on behalf of your application. And of course you have to confirm the redirect URI when calling the API using the redirectUri property.
You can find more on this in the OneDrive File Picker SDK docs and on their set up section.
EDIT:
If you have a dynamic url for your picker, you will need some fixed redirect route. This can be http://localhost/redirect. Before starting the Auth flow, you have to store the current state/route, e.g. inside local storage. After the redirect, you finish the authorization and redirect the user once again to the previously stored state/route.
The point on redirecting the user to your own application and not to their OneDrive is, that your application wants to access the files. If the user gets redirected to OneDrive, maybe they will see their files, but OneDrive will not know how to send the information back to your app. If you redirect to your app, it stays in control of the UI, can prompt the user to select a file and receive the selected file using the OneDrive SDK.
Maybe it will help you to follow along the Microsoft docs to use the SDK right away instead of building up on an undocumented third-party component.
Go to you client app you (I assume) opened in Azure, you need to register the base URI of your choice - you can see a full guide here:
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app
Under "Add a redirect URI"
I have 4 angular applications one is a landing app which asks user to login and has to redirect the user according to its type
to one of the other 3 applications. I am unable to figure how to should i achieve that.
Have the three apps running on different subdomains. Upon login backend send a redirect response, figuring out what type of user it is?
But this leads to cors Error. Also i am not sure whether the cookie which i am setting will be accessible in all the subdomains or not.
Is there a way out?
You can do a redirect, but it seems like an unnecessary step (and kind of convoluted for this type of application).
Instead of returning a redirect based on login, it seems more straightforward to just return the address you want to redirect to in the response. Trigger a lookup to determine which app you should be directing to (however you're doing that) and then return the address of the app in the response data. From within Angular, you can extract the address from within response.data in $http. (see angular docs). The nice thing here is you also keep routing control and knowledge of state within Angular itself.
As for the apps themselves--instead of a subdomain, you can simply put the apps into different folders on your domain. This deals with CORS and the cookie issue.
Otherwise, you'd need to set a CORS header. You would do this on whatever backend you're sending the requests to--there's usually some sort of library to make it easy, for example, Flask CORS for Flask. If you need to share cookies in this case, this StackOverflow answer discusses one way of doing it (using an intermediary domain).
Generate a security key for the user session with some TTL in an authentication table when you authenticate the user with your App1
Redirect the user to any other app in any domain with this security key where they can query the authentication table and verify the user.
Let these other applications work on their own (in the front end) and communicate with the back-end with the security key when necessary.
Lot of PHP frameworks has built-in support for this mechanism. My favorite is Silex.
I have an application built in symfony 2.3 and FOSUserBundle for authenticating its users.
This application serves multiple users based on urls, pages looks like this /urlidentifier/login. This urlidentifier is a variable and it look for a [0-9A-Za-z] + to fill that slot.
FOSUserBundle config params like Login check path and logout path are saved and cached to a file (Symfony frozen parameter).For a single website user are easily authenticated with prefixing the FOSUserBundle parameters as well as Routing.
The real issue occur when the user are switch through multiple url (super privileges)
Scenario
When a super admin is logged and authenticated via urlidentifier1/login. He could switch himself to another website without logging out. Now the url changes from urlidentifier1/index to urlidentifier2/index, he would be logged in, But when he tries to logout, The parameters like logout path would be urlidentifier1/logout. When logout is triggered we will get an error like
"You must configure the logout path to be handled by the firewall using form_login in your security firewall configuration...”
How can I make the backend use such dynamic URLs?
I would like to develop an "twitter-like" application where users can showcase their artwork on a simple interface like twitter. Obviously I also want to provide a simple URL for each user (e.g domain.com/myuser) but I found that GAE doesn't allow naked domains anymore so I did a DNS redirect as per google docs http://www.google.com/support/a/bin/answer.py?hlrm=en-in&answer=61057 so when users type domain.com they are redirected to www.domain.com.
The problem is that when they type domain.com/myuser they are redirected to www.domain.com too and the username is lost which is quite annoying so I would like to know if you can recommend me a feasible solution.
Should I catch the referrer URL to find what user was typed on the naked domain ? Is there any other solution ?
How URL forwarding works depends on the provider. If your provider doesn't include the path when sending a redirect, you should find one who does - zoneedit, for instance.
These guys also offer a free service that merely redirects (domain) to www.(domain) when it's IP is listed as an A DNS entry. http://wwwizer.com/
(Using CakePHP) I'm looking to setup a sub-domain for user creation, password changes and credit card information vies...as in:
secure.mydomain.com (https)
- User/Create
- User/Login
- User/UpdateCreditCardInfo
app.mydomain.com (http)
- once logged in using the "secure" site, the user will be able to access application specific views
Using the CakePHP Auth component on both my sub-domains...how do I persist the login information when the user is authenticated on "secure" then is redirected to "app" sub-domain?
See: http://book.cakephp.org/view/173/Sessions
To provide a custom configuration, set Session.save Configuration to a filename. CakePHP will use your file in the CONFIGS directory for the settings.
Configure::write('Session.save','my_session');
This will allow you to customize session handling.
// Cookie path is now '/' even if you app is within a sub
// directory on the domain
$this->path = '/';
ini_set('session.cookie_path', $this->path);
// Session cookie now persists across all subdomains
ini_set('session.cookie_domain', env('HTTP_BASE'));
That's a general problem with cookies. They're only valid within the domain they were set and its subdomains. app.example.com is not a subdomain of secure.example.com, so you can't transition cookies between them.
You can set a cookie at example.com and make it valid for all its subdomains, including app. and secure.. You can then modify the cookie on these subdomains.