IIS keep prompting Windows Credentials on 401 with IISNode - node.js

I'm hosting a web application built with NestJs and React (NodeJs) in an IIS Server with IIS Node. To secure my app, I'm using a system with JWT Token + Refresh Token and Windows Authentication to automatically get the connected user and so generate tokens.
Everything (almost) is working fine, but I have a problem with the Windows Authentification. Each time the JWT Token of my application expired (so the API returns a 401 error page) and only after a refresh of the navigator page, the navigator prompt again the pop up to set windows credentials. The logic use case on this is that one day you're using the webapp, and some days later you want to use the app again, but your token is expired, 401 error, windows credentials is prompting.
If the token expires, and the user simply navigate to another page (so no page refresh with my React SPA) there's no problem, the JWT token is refreshed with the refresh token thanks to the API.
I've already tried some stuff:
Disable Loopback Check
Enable Anonymous and Windows Authentication
Changing some random settings
But I haven't found a solution yet.
My goal is to only have the Windows Credentials display once, when the user visits the page for the first time.
As I'm out of ideas, I'm considering setting a JWT that never expire, but of course it's not a great solution.
Thank you very much for your help!

I ended up using a custom 4xx code to handle my 401. So if my API is sending me a 499 http, I know it mean for my frontend that the session is expired. Hence, I don't have the prompt for Windows Credentials.

Related

How do you implement a custom login UI when using PKCE in auth0?

I am setting up a login system in auth0 for a React Typescript application. Due to how the application works I am using the PKCE flow for authentication and authorization to get access tokens and refresh tokens. So far I have implemented the flow by adding a node js express server that fetches the access token and refresh token from auth0 once we have the authroization code after logging in through the /authroize endpoint on auth0. However the problem we have now is that we cant implement our custom UI onto the login page since when we hit the /authorize endpoint we are sent to the login page hosted at auth0. We would want to set up our own login form and send over the details to auth0 in order to fetch the authorization code. Is there a way to login through our own login page instead of using the one hosted by auth0, by for example hitting the right endpoint in their api to fetch an authorization code? The only other option I have seen is by changing the HTML under branding in the application dashboard but I have also read that auth0 does not recommend doing this.
I have also previously used the auth0 js SDK and there I was able to use our own custom page for login, however that SDK uses the implicit flow which does not issue refresh tokens and cannot therefore be used. In the other SPA sdk, you cant add your own UI for login since that redirects you to auth0 as well.
Assuming that you still use the Node.js server in addition to the SPA, you can ask the user for username and password, send it the Node.js server. Using the Resource Owner Password flow, the Node.js server can then request the access, refresh and ID tokens.
Please study the security implications carefully, in particular related to this authentication flow.
By implementing custom login UIs, you lose many things: hardened security of Auth0 servers, easy configuration of authentication methods without changing the application, use of ready-made Auth0 SDKs etc. I would carefully consider if it is worth it.

Cache tokens in azure app service authentication (EasyAuth)

I'm using azure app service built in authentication to log in users to my web app. Since I have some pages that user can access without authentication I have allowed anonymous access in app service auth configuration.
It works as intended for the current session. But when the user closes the browser or opens a new window, the authentication is lost. The user is required to login again.
Is there any way to keep the user logged in?
What I do currently:
On sign in button click,
direct the user to /.auth/login/microsoftaccount, after successful login I call ./auth/me to get the user claims/details and then login the user. Then I do a http post to https://appname.azurewebsites.net/.auth/login/microsoftaccount to validate the tokens that I got from /.auth/me and I also get a session token from this post request (which I don't know what to use for).
I use the custom headers set by the app service for authentication on the backend. App service auth docs
Is this the right way of doing authentication using app service. If so is there any way that we can keep the user logged in to app service auth and not ask them to sign every time they open the website.
Is there any way to cache the tokens?
It is normal that you need to login again after close your browser or open in a new window, because the life cycle of session is from opening the window to closing the window.
You could consider using cookie coordinating with session. Session is on server side, we cannot see it, but we could set the time out value. Cookie is on client side, we could save some authentication information to stay login, but it is not safe.

AAD Refresh Tokens with Ionic 2 PWA

I have an Ionic 2 app that works as a native app and as a progressive web app hosted on an Azure Web Site (which is not the same site as my API App Service Site). On the mobile side, I can get refresh tokens successfully by using the mobile SDK's login method and the making the REST call. However on the web side (PWA), I can't use the SDK to login because InAppBrowser won't work because login.microsoftonline.com sets X-Frame-Options to DENY. Therefore, I redirect the browser to /.auth/login/aad?session_mode=token&post_login_redirect_url= with a redirect URL coming back to my PWA index page. That sends me the token back via #token which I am able to parse and use to successfully authenticate to my back-end API.
What doesn't work for me is calling /.auth/refresh. That always gives me the error:
The refresh request issued by sid... failed because no refresh tokens
were found in the token store.
The API App is configured to return an access token for graph.microsoft.com and I can see the refresh token in an initial call to /.auth/me. I can also login directly via a browser session using /.auth/login/aad and no parameters. There I can call /.auth/me and /.auth/refresh successfully
So what I am trying to figure out is how to make this work in the browser. I need the user to get redirected back to my app so I specify the post_login_redirect_url parameter. With that the user gets logged in successfully and redirected to my app. However, that is when the call to /.auth/refresh fails with the error above. I am hoping this is just a matter of not passing the right parameters to the login endpoint but I am not sure.

Google Oauth2 Contacts API returns Invalid token: Stateless token expired after an hour

What's wrong with my setup?
I am using django-allauth for social signup and recently i added contacts to it's scope. Things are working fine. It now asks for permission to manage contacts and I am able to get contact details of users through the API.
But once i make a request to get contacts of a user(I am not saving any refresh token or accss token at that time), after an hour when i make the request again with same token, It shows this error "Invalid token: Stateless token expired".
However I can still login into the website and the token does not change. However when I logout and login again the token changes and i can again get the contacts using that token for one hour.
What's the issue? What am I missing?
See, when you are logging into the website, you are probably using cookies. So basically you might be using the same session and actually the api is not called.
The time when you are logging in incognito mode or in a diffrent browser, that cookie cannot be used, so this time api is called. For this reason, the token is getting changed.
For example, if after few users have signed up with google, you change the scope of the app, what happens is, if the user has enabled cookies and it has not expired, when he visits your site, it simply logs him in. It does not asks for permissions (that you added recently to scope). But when he logs out and logs in again, then it asks for the additional permission and th token also gets changed.
What you should do is, you should go through th codes of django-allauth and clear it out how they are using the token. You must also know that for getting refresh token, you must have offline access enabled in your configuration.

Authentication strategy between my chome extension and server

I'm in the process of building a Google Chrome extension, and have some questions about how to implement security into the application.
I need to access a couple of Google API's so am going to be using OAuth 2.0 for that. So basically from the extension I know which user is logged into the browser.
My extension then needs to get and post data to my (nodejs) API service. I want to ensure that the user requesting data is the same user that is logged into the browser. Is there any way of using the previous Google authentication process to also authenticate communications between the extension and my API? I dont really want the user to have to log in again, to access my API.
I'm sure I'm missing something simple, and I've not been able to find anything that fits this scenario
Follow the OpenID Connect auth flow and you will get an access_token and an id_token. The acess_token you will use to use to make authenticated requests to Google APIs as usual. The id_token will be used as authentication with requests to your server.
When the requests hit your server you will need to validate the token and you can then use the contents of the id_token to identify the user.
User wouldn't have to login on auth process provided if user is already logged in and you are using a web application flow (not chrome.identity APIs) but user would see the consent screen atleast the first time. However you can skip the account selector screen if you already know the email address by providing &login_hint= parameter.

Resources