MSAL requests HTTP page and a "Mixed Content" error is thrown - azure-ad-b2c

I am playing a bit with MSAL for auth operations with Azure B2C. For some reason it tries to redirect the user to the HTTP endpoint instead of HTTPS one while acquiring token with popup. My app has HTTPS redirect URL in B2C. The MSAL configuration has the same redirect URL set up. I can't find any place where MSAL or B2C would have any HTTP endpoint configured. The error is:
Mixed Content: The page at 'https://MYPAGE.com' was loaded over HTTPS, but requested an insecure frame 'http://MYPAGE.com/#error=interaction_required&error_description=AADB2C90077%3a+User+does+not+have+an+existing+session+and+request+prompt+parameter+has+a+value+of+%27None%27.%0d%0aCorrelation+ID%3a+302a0615-b431-4a4d-9104-f58e3a8229ab%0d%0aTimestamp%3a+2020-08-10+06%3a46%3a11Z%0d%0a&state=eyJpZCI6IjI0Y23jYTJkLWQxMjUtNGZlNy05NjBjLWI0NTkwNWE5NWJlYyIsInRzIjoxNTk3MDQxOTc0LCJtZXRob2QiOiJzaWxlbnRJbnRlcmFjdGlvbiJ9'. This request has been blocked; the content must be served over HTTPS.
Interestingly, in the end the auth works, however, with that error it takes more time to load the popup that acquires the access token.
When I run my site locally on http://localhost:8000 this problem does not occur at all (since it's http anyway) and token is acquired much faster.

Related

Reading authorization response for HTTP AD login

I am trying to implement Active Directory login for my webpage. The webpage is hosted on a Node.js server that can talk to a the AD server via LDAP (so it is not on the same physical machine right now).
To trigger the login request, I send a 401 and WWW-Authorize: Neogiate response to a GET request triggered when the page is loaded. This causes Chrome to open a Username/Password dialogue. However when I enter some info and click Submit, I do not see any of the username/password data. Instead I see this authorization: 'Negotiate TlRMTVNTUAABAAAAl4II4gAAAAAAAAAAAAAAAAAAAAAKAGNFAAAADw==' which when decoded is this NTLMSSP cE
I am not sure what to do with this token or how to proceed.
You are running into this error because the server is directing you for implementation and Protected GSSAPI Negotiation Mechanism. This is a Microsoft invention for negotiating a type of authentication to use for Web SSO (single-sign-on):
either NTLM
or Kerberos
You need to store this token into the localStorage or cookies.
For example when you get the token from the server you then can save this on localStorage like this:
localStorage.setItem('token', token);
Then when you call the API you then have to send this token to the server with the request.

Can a browser app (spa) access MS Graph without a logged in user?

I can register an app in Azure as 'Web' application, specify the permissions it needs to read from Graph, consent to the permissions as an admin, create a client secret.
I try using the client secret in the app to request an access token. But MS identity platform rejects grant_type=client_credentials /token endpoint requests that come from a browser.
But how does it even know the caller is a browser? The same requests works when it is sent via Postman!
Obviously, CORS makes the difference: When a browser executes the request from myserver/myapp.js, it sets the 'Origin' header in the request going to login.microsoftonline.com and, by registration as a 'Web' app, does not send back an Access-Control-Allow-Origin response to the browser - the browser refuses to get the response. On the other hand, when Postman executes the request, it uses it's cloud agent to run the request. The agent doesn't send an 'Origin' header and doesn't check the response header.
Is there a different way an app in a browser can call Graph without a logged in user?
The answer is No. based on this Azure AD official doc, if you want to get an access token on SPA, only OAuth 2.0 implicit grant flow and OAuth 2.0 authorization code + PKCE flow are supported but both of these two flows require users' interaction to login.
Cross-origin resource sharing (CORS) is a browser mechanism. Your request is blocked by your browser, Azure AD endpoint does not care about what kind of app sends the request.
This is a similar question answered by MVP: #juunas.

Redirect has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header

I am working on Azure AD interactive login from my webapp. When a user logs in to my site he is redirected to the Azure login page, authenticated and returned to my site. This process involves a request to login.windows.net which redirects my browser to login.microsoftonline.com(which does the authentication).
However I am getting a cors issue which states that redirect to login.microsoftonline.com has been blocked doe to no "Access Control Allow Origin" header from the requested source. I know it is possible to add this header when the requested resource is in my webapp, but in this case its not. My question is if login.microsoftonline.com doesn't return the header which causes this, how can I handle this issue from my webapp? Below is the error on my browser console.
XMLHttpRequest cannot load
https://login.windows.net//oauth2/authorize?…......-4129-adea-
ccdcbdeaa80e&nonce=c962fb8a-3c8c-4dec-9fbc-4f2fb8fcfde1. Redirect
from
'https://login.windows.net//oauth2/authorize?…......-4129-adea-ccdcbdeaa80e&nonce=c962fb8a-3c8c-4dec-9fbc-4f2fb8fcfde1'
to
'https://login.microsoftonline.com//oauth2/au….......-4129-adea-ccdcbdeaa80e&nonce=c962fb8a-3c8c-4dec-9fbc-4f2fb8fcfde1'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin 'https://my_host'
is therefore not allowed access.
I was able to bypass this issue by passing the redirect url to a form action and triggering the submit using Javascript instead of directly redirecting to the url. CORS check is not done when the request comes from a form submit.

how .htaccess authentication works with my website via LDAP. How the cookies and sessions are set?

I am using .htaccess authentication for my website. Once the authentication happen with AD vi LDAP, how the authenticated user's session and cookies got created in the browser and where the redirection is really happening to my website. Please help in this or please share any links which explains this process.
Take a look at the wiki pages for BASIC authentication and DIGEST authentication, both is an authentication mechanism that is on the protocol (HTTP). Basically, this is what the browser sees (heavily paraphrasing here):
Attempt to request a URI, webserver replies with a 401 response and a WWW-Authenticate header
This header contains a REALM, kind of like a group of pages that all belong to the same authentication realm
Browser pops up a modal dialog box asking for a username and password.
Depending on BASIC or DIGEST, that password is sent back to the webserver along with the original request that resulted in a 401.
If the credentials are incorrect, a 403 is returned and the browser shows an appropriate error message. Otherwise, the webserver returns the requested page.
The browser knows this URL belongs to the REALM, so every time this URL is requested, authorization is automatically sent along with the request.
If the browser requests something else that also requires authentication, and it belongs to the same REALM, the browser will automatically send the authorization when the webserver returns a 401 and the REALM.
How the webserver is configured with REALM info and a list of credentials varies. It could be hooked up to a LDAP database, Active directory, a flat file with hashed passwords, etc.
This is different than cookies or other webapp-level authentication because it doesn't use the HTTP protocol to authenticate. The webapp has a page with forms for a username and password, those are sent via a POST/GET request as parameters, and it's up to the webapp to determine if those credentials are valid. If they are valid, the webapp could choose to store a session ID as a cookie so the browser can continue to browse pages served by the webapp.
One of the end-user differences between this and HTTP authentication is that the webapp can delete the cookie, or invalidate that session, essentially logging the user out of the webapp. This isn't really possible with HTTP authentication because the browser blindly submits an authorization header when requesting pages under the same REALM. One way to get around this is to make the webserver forcefully return a 403 when a protected page is requested.
Another difference is that with HTTP authentication, you can include a username/password as part of the URL. How does http://user:pass#host.com authentication work?
Also see: http://blog.distributedmatter.net/post/2008/06/09/HTTP-authentication-mechanisms-and-how-they-could-work-in-Restlet for a more complete description of authentication in general.

REST API Authentication with same origin policy and OAuth

I am writing an API to be used by both my JavaScript app (same domain, API is at api.example.com and site at example.com and 3rd party developers (mobile, desktop, etc). Now I want to use OAuth but I have no idea how the workflow is when using both OAuth and using my application with the same origin policy.
How do I authenticate the user in my web app? When I send the username and password, can I check if the request came from my domain and then return the token? The token will be stored in a cookie and sent back to the server on every request. So there are 2 parts:
If the request came from my domain, just check for token else throw HTTP exception.
If not my domain, do OAuth authentication.
Is this possible? How do I go about setting this up in asp.net web API? (mainly the part about checking if the request is in the same domain)
I am guessing that to log into your web app you're not using OAuth, but simply accept username and password and start a session? If so you don't really have to bother with OAuth for your own site.
Set up the session cookie to be valid across *.example.com and you should be able to validate that cookie both on site.example.com and api.example.com.
Example:
Request comes in to api.example.com/verify_credentials.json
Serve response if OAuth validation is successful.
If not, attempt Cookie validation - serve if successful
Return 402 Unauthorized if both fail.
Here's a thread about sharing a cookie across sub domains: ASP.NET Subdomain Cookie (parent and one subdomain)

Resources