I am writing a mobile application for an already existing web app. In the backend, I implemented the usual cookie-based session ID authentication. with a CSRF token generated on login and sent with each request in a custom header.

the problem is that I want to use the same backend for both the mobile app and the web app.

using an HTTP-Only cookie is good against XSS attacks. but it makes it hard to use with a mobile application. And while researching I found that I shouldn't rely on http-only to protect against XSS and rather rely on the front-end code not to allow JS Injections.

What I have tried is:

  • On login. send the session ID in both a cookie AND in the body.
  • the web app uses the cookie with CSRF to authenticate
  • the mobile app uses the session id provided on login to authenticate. like a usual bearer token. send in a custom header.

Is this secure? are there any security risks to this method?

Note: the CSRF token will only be sent by the web app since it is the only vulnerable environment. the backend checks whether the session ID was sent in a header. If so. no CSRF is required, since headers are not set automatically by the browser.

  • if the backend requires the sessionID to be read from a custom header in every request and you haven't loosened CORS restrictions (everything is same-site), you should already be safe against CSRF. Pre-flight requests will be sent. Just make sure that no standard POST or GET can change state on the backend. The backend can be the same for both web app and mobile app. Be sure to mitigate against XSS. Dec 6, 2023 at 18:12
  • The http-only cookie protects against XSS stealing the session credentials. Since you won't have that, you should require the user to re-enter their username/password when changing account info such as changing password or e-mail. Dec 6, 2023 at 18:27

1 Answer 1


If implemented correctly, sure, that's secure. Not sure why you went with a custom header rather than Authorization: Bearer, which is a well-established pattern, but it doesn't matter for security. You're also correct that this approach is inherently secure against CSRF, and that HttpOnly alone is nowhere near sufficient mitigation for XSS.

With all that said, you might want to consider unifying the web and app client interfaces. Right now, you have two code paths that are both operational for authentication. That's... risky. It's not necessarily unsafe, but it increases the odds of mistakes like "you patch a bug in one path but not the other" or "you add some code that makes a security decision based on the 'fact' that the cookie/header will always be present for authenticated requests".1 In other words, it's more brittle. (It also just means more maintenance, and a little more attack surface.) On the other hand, even though XSS is still a serious problem even with HttpOnly cookies, it is worse without them, so if you do this then you are slightly increasing the impact of any XSS that should occur.

1 For an example, imagine your anti-CSRF check looks like this: IF authHeader != null OR validate(anti-CSRF-token), in which case an attacker could potentially achieve CSRF - CORS permitting (which it normally wouldn't, but we're already positing you made a mistake, and lot of people run over-permissive CORS) - by using the webapp and submitting a random value in the auth header that the mobile app uses. The server would still validate the user based on the cookie, but would (in that case) ignore the lack of anti-CSRF token.

  • I only implemented one authentication path for both web and mobile. but the function checks whether the header is set. if so validates it (Header not set automatically, no CSRF risk). else, validates the cookie AND CSRF token. If the header is not validated. it just skips the whole section and goes to validate both the cookie and CSRF.
    – TommyGun
    Dec 6, 2023 at 13:16
  • As for the custom header. Authorization: Bearer is reserved for api keys that I use for webhooks with 3rd party services and APIs. since the header is already used I figured I might as well use a custom header.
    – TommyGun
    Dec 6, 2023 at 13:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .