Azure App Service optional incoming SSL certificate forces prompt in browsers - ssl

A simple ASP.NET Core 3.1 backend is running on an Azure App Service, where the Incoming Client Certificate option is set to Allow (the app integrates with other apps, using SSL certificate based authentication). Nothing was configured in Startup.cs to do any magic with the incoming certificates (where the app's interested in the incoming certificate, the controller just reads it via Request.Headers["X-ARR-ClientCert"])
However, a React frontend (running in another App Service) uses MSAL to authenticate with the backend App Service, using Azure Active Directory/OAuth 2, not SSL certificates, the X-ARR-ClientCert header is not populated at all (the HTTP client being axios).
Some users, when trying to access the app get a popup from seemingly all different browsers, asking to specify which certificate to use for authentication (Site "backend" needs your credentials):
Not all users are prompted with this popup, it happens seldomly. Is there any known way to configure either something in the App Service, React frontend (axios) or even in the Startup of the ASP.NET code to not-trigger this popup? In the App Service, it'd be impossible to put all routes into the Certificate exclusion path.
One idea seems to be to set rejectUnauthorized to false when setting up axios, however I'm unsure if this is a safe approach:
axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false,
})
});

Related

What is purpose of Client secret if it is not used for Google SignIn in React Natvie (ios/android) app having Backend api? How is this secure?

I have react native app(lets say ABC) from where I am going Google sign in, I get the idToken and send it securely using Https to backend server, it then validates idToken and gets accessToken. But in this entire process clientSecret is not used anywhere. My Client Ids can be used by anyone, let's say app XYZ to access user data. How is this secure?
On the other hand in my react website and backend server where I was using passport, client secret was needed. Am I missing something here?
And if the process used in native app is secure, I can use same process in react website, i.e. get rid of passport strategy.
Client ID is included in HTML served to browsers, as you point out it's not secure--nor is it intended to be. The Client ID simply identifies the app.
For Web apps Authorized JavaScript origins are required, and for back end services Authorized redirect URIs are also necessary. Requests/responses are verified by Google's OAuth service using these settings.
HTTPS, which includes a signed certificate is required and helps ensure traffic originates from source hosted and served from your verified domain.
For sign-in responses typically use a signed JWT that can be securely verified on the back end (unless OAuth 2.0 or gapi is used).
Client Secret, should of course never be included in HTML served to a browser and should be kept only on a secure location, out of source control, and on the back end server.
Use of a nonce would also help you avoid replay attacks. See the
state variable for pure server side apps, or Sign In With Google nonce attribute.

Auth0 - OAuth login with dynamic callback

I want to secure my Web-App with Auth0 in React. This means a user can login on my page and use the resulting Access Token to make requests to services behind AWS API Gateway.
But Auth0 requires that all possible Callback URLs are defined in the Dashboard.
This works well as long as the Application is hosted on a domain owned by me.
In my case the React App will be distributed as a Plugin (Shopify, Woocommerce). My users will install this Plugin and use my App through their shopsystem-UI. Which means that requests from the browser are made from their domain.
How should I securely access my Services through this client which is distributed on Domains which i don't know beforehead?
As my research shows, one solution would be Dynamic Application Registration. But with this I would end up with one Auth0 Application per user and Auth0 Limits that to 100 Applications.
How should I handle my case instead?

Is it possible to use a bearer token to authenticate two webapi systems on the same server?

We have two webapi applications (core and support) configured on the same IIS web server running on our local domain. Our users authenticate on the core application using active directory and the core system returns a bearer token. This token is then used to authorize all API calls from our ReactJS client. In addition to the core application, we also have the support web application. Any calls to this system API end points also needs to be authorized.
Is it possible to use the same bearer token issued by the core application for the support application?
We have configured a separate webserver, database server and client to test the process. After building and deploying the two api web applications and the ReactJS client we are able to login via active directory, receive a bearer token and with this token authenticate on both the core and support platforms.
However, when we copy the same files and configurations to our clients server, we get a 401 authorization error on the support domain; the core domain works perfectly.
We have installed SSL certificates in both environments as well.
If we set the support application to Allow all Origins for CORS it works as there is no authorization. However, when we set the origins to the ReactJS and Core api projects we get the 401 error on the support domain.
We did not expect the token from the core application to authorize against the support application. However, this is working within our domain environment and we are not sure why. This has made it even more confusing as to why it does not work in the customers environment.
In case it helps anyone ... The reason this worked for us internally is because we had all web applications running within the same application pool. This meant they shared the same machine key and as such the bearer token from one would be authorized across all. As soon as we moved them into their own application pools we were able to replicate the same issue as the customer (ie. 401 authorization). The fix is to either have them in the same application pool or add the same machinekey to the applications web.config files.

Secure App with Api server with static jwt token

This may have been asked but maybe 2018 there is a better way. I"m trying to secure my api server and only grant access to my client apps I have created. Mobile / Web client apps that is using vue.js for client app and express.js on node for api server.
Would is be wise to create a static token code it in on the client app. It would be sent with every api call. Then on the api server have my secret to the token. Verify the token before api call can be sent back.
Is there a better way? It seems to work fine but maybe there is something I don't know. Maybe everyonce and a while replace the static token and secret? The network would be https for sure. I am sending the token with every api call req.body.clientAppToken
What do you think? Thanks everybody!
Update this is express api middleware below.
App sends a manually created token to the api server on every request. Token is the same for all apps. I verify the token with the secret stored on the server. If it passes they get the data if it does not they do not.
const jwt = require('jsonwebtoken')
const config = require('../config/config')
module.exports = {
authClientAppToken (req, res, next) {
// start see if client app jwt is correct
/* eslint-disable */
console.log('req.body.clientAppToken', req.body.clientAppToken)
try {
let decoded = jwt.verify(req.body.clientAppToken, config.jwtAppSecret)
next()
} catch (err) {
res.status(400).send({
error: 'We got problems'
})
}
/* eslint-enable */
// end see if client app jwt is correct
}
}
I"m trying to secure my api server and only grant access to my client apps I have created. Mobile / Web client apps that is using vue.js for client app and express.js on node for api server.
The cruel truth here is that you cannot truly secure a web app because any kind of secret, be it a JWT token, a signed JWT token, an API Key or anything else you may want to use is very easily retrievable on the client side just by using the browser developer tools, aka F12.
On a mobile app developers may think that once they ship a binary that they can hide a secret there and keep it safe, well mobile apps are not as trivial to look into as using F12 in the browser, but they are easy enough to reverse engineer with tools like the Mobile Security Framework, that will extract all the code in the binary, thus exposing all the secrets stored on it. But even if the secrets are computed at runtime this tool is capable of doing runtime introspection on what your mobile app is doing, thus able to extract also dynamic computed secrets.
Would is be wise to create a static token code it in on the client app. It would be sent with every api call. Then on the api server have my secret to the token. Verify the token before api call can be sent back.
So as said previously any secret generated or stored in the client side can be extracted and reused outside of the scope it intended to. Despite this I still encourage the use of them as 1 more layer of defence.
It seems to work fine but maybe there is something I don't know.
I would recommend you to go through this series of articles on Mobile Api Security techniques to understand how https, certificate pinning, api keys, tokens, HMAC can be used to secure the API server and how they can be bypassed. While the article is in the context of a mobile api, almost everything applies in the context of an API serving a web app.
Maybe everyonce and a while replace the static token and secret?
Using short lived expiration times on tokens is wise and recommend, but they just make the window where they can be malicious reused shorter but they will not prevent API abuse.
The network would be https for sure.
While https should be always used by itself only guarantees that the data in transit is encrypted and cannot be readded by third parties, thus protecting the secrets in transit but will not prevent them to be reverse engineered from the app itself.
Is there a better way?
For web apps you can make it hard by using a javascript obfuscation tool, implement reCaptcha V3 and if you want to go more advanced a User Behaviour Analytics Software solution on your API server.
Regarding mobile apps is possible to build them in a way that is not needed to store secrets in them in order to pass down in each call to the API server. The technique is called Mobile App Attestation and consists of a mobile sdk and a cloud service that work together to ensure that the mobile app is the same one uploaded to Google Play or to the App Store. The mobile sdk runs in the background and communicates with the cloud service that will issue a valid JWT token when the app is the original one and is not running in a jailbroken or rooted device or being object of a man in the middle attack. A valid JWT token is one that is signed by a secret only known by the cloud service and the API server, the mobile app does not know it at any moment, thus is not possible to reverse engineer or fake it. An invalid JWT token only differs from a valid one by being signed with a secret not known by the API server, thus making it indistinguishable from a valid one. This type of security solution can be found at Approov and this is where I currently work.

Web API authentication without username password

I've a simple web api configured for local authentication. This works fine.
I've a console application with httpclient implemented to consume the web api.
When the console app runs it sends credentials in header and receives token and normal operations work.
Since I want this app to run in background and want to keep the user intervention minimal, is there anyway I can do away with username/password without compromising on security aspects.?
Passing on username and password through headers is not a security threat, what you can do to make them safe is encrypt them before sending and then decrypt on API side also make your Web API over HTTPS to make it more secure.