#How to pass headers/cookie in microservices setup

1 messages · Page 1 of 1 (latest)

lucid creek
#

Currently, I have 2 applications:

  • users -> capable of crud operations for users. It also has the ability to generate and validate JWT
  • external-app -> capable of other operations (e.g. adding 2 numbers)

Both are hosted on a local machine at port 8001 and 8000, respectively. I utilized NGINX to perform a reverse proxy at port 8080.

When I access http://localhost:8080/users/login or any other endpoint from the user service, I can get a cookie and header value. However, I don't know how can I pass that data to the external-app so that I can just validate the token and check if the user is authorized to use it.

P.S. the external-app is accessible publicly in my local machine. I want to change that by adding an authentication (this is where the passing of JWT comes in to authenticate the user).

PPS. Unfortunately, I am unable to post the code here for external-app. That's why I just used the adding of 2 numbers as an example.

native voidBOT
#
Notes for How to pass headers/cookie in microservices setup
At your assistance

@lucid creek

No Response?

If no response in a reasonable time, ping @Member.

Closing

To close, type !solve or byte solve.

MCVE

Please include an MCVE so that we can reproduce your issue locally.

gloomy thistle
#

I do not have a suggestion to make, I am asking this purely for my understanding 🙂

any other endpoint from the user service, I can get a cookie and header value.
if I do GET: /users/<some_user> I get a cookie and header even now?

how can I pass that data to the external-app so that I can just validate the token
is extenal-app an "Auth service" that does the authentication and authorization?

lucid creek
#

if I do POST: /users/login and some random endpoints in the same application (which is the user application) I get a cookie and header even now?
yes, it has some value.

is extenal-app an "Auth service" that does the authentication and authorization?
For this, it has no auth service just plain routing and some data that needs to be shown. (This is where I needed to add authentication)

Here are some images for the USER service

#

I have tried directly passing the authorization and cookie in the NGINX config file and have obtained the desired result (having the data in the cookie and headers)

lucid creek
# lucid creek

My only problem now is If I logout the user, I can still access the content for this

crisp moss
#

I'm having a hard time following you

lucid creek
#

apologies, here's the mcve:

project #1: User authentication

from datetime import timedelta

import uvicorn
from litestar import Litestar, post, Response
from litestar.exceptions import HTTPException
from litestar.security.jwt import OAuth2PasswordBearerAuth, Token, OAuth2Login
from pydantic import BaseModel

from app.users.utils.authentication import jwt_auth


class UserLoginSchema(BaseModel):
    email: str
    password: str
    role: str

async def retrieve_user_handler(token: Token) -> None:
    ...

jwt_auth = OAuth2PasswordBearerAuth[UserLoginSchema](
    retrieve_user_handler=retrieve_user_handler,
    token_secret="abc123",
    algorithm="HS256",
    token_url='/login',
    exclude=["/login", "/schema"],
    default_token_expiration=timedelta(minutes=30)
)


@post("/login")
async def login(data: UserLoginSchema) -> Response[OAuth2Login] | HTTPException:
    return jwt_auth.login(data.email)


app = Litestar(
    route_handlers=[login],
    on_app_init=[jwt_auth.on_app_init],
    debug=True
)

if __name__ == "__main__":
    uvicorn.run(app, host="localhost", port=8000)
#

project #2: Internal/private urls

import uvicorn
from litestar import Litestar,get

import os

from litestar.exceptions import HTTPException
from litestar.middleware import (
    AbstractAuthenticationMiddleware,
    AuthenticationResult,
)
from litestar.connection import ASGIConnection
from pydantic import BaseModel
from litestar.security.jwt import Token


from pydantic import BaseModel
from enum import Enum


class UserRole(str, Enum):
    GUEST: str = "guest"
    ADMIN: str = "admin"


class User(BaseModel):
    id: str
    first_name: str
    last_name: str
    role: str


class TokenSettings:
    SECRET_KEY = os.getenv("SECRET_KEY")
    ALGORITHM = os.getenv("ALGORITHM")


async def decode_token(encoded_token: str) -> Token:
    decoded_token = Token.decode(encoded_token, secret=TokenSettings.SECRET_KEY, algorithm=TokenSettings.ALGORITHM)
    return decoded_token


class MyAuthenticationMiddleware(AbstractAuthenticationMiddleware):

    async def authenticate_request(
            self, connection: ASGIConnection
    ) -> AuthenticationResult:

        raw_token = connection.cookies.get("token", None)
        if raw_token is None:
            raise HTTPException(status_code=401, detail="You are not authenticated")

        cleaned_token = raw_token.split()[-1]
        token_data = await decode_token(cleaned_token)
        user = User(
            id=token_data.sub,
            first_name=token_data.extras.get("first_name"),
            last_name=token_data.extras.get("last_name"),
            role=token_data.extras.get("role")
        )

        return AuthenticationResult(user=user, auth=cleaned_token)


@get("/private-url")
async def private_url() -> dict[str, str]:
    return {"title": "Private Calculator"}


app = Litestar(
    route_handlers=[private_url],
    debug=True,
    auth_mw = DefineMiddleware(MyAuthenticationMiddleware, exclude=["/schema"])
)

if __name__ == "__main__":
    uvicorn.run(app, host="localhost", port=8001)
#

I used NGINX as an API gateway:

server {
        listen 8080;

        # Location for authentication
        location /login {
                proxy_pass http://localhost:8000/login;
                proxy_set_header Authorization $http_authorization;
                proxy_pass_header Set-Cookie;
        }

        # Location for private urls
        location /private-url{
                proxy_pass http://localhost:8001/private-url;
                proxy_set_header Authorization $http_authorization;
                proxy_pass_header Set-Cookie;
        }
}

I also used NGINX to pass the header and cookies to other projects (Not sure if this can be done in the code itself

#

What I want to achieve is to prevent anyone who's trying to access the /private-url If there's no valid token in the header/cookie.

Basically, I am creating a microservice using Litestar that has a SSO to access all private endpoints (Depending on their role)

mystic furnace
#

it doesn't know about anything the other application does, where you have set up your oauth stuff

#

Your external-app needs to be able to verify the JWT if that's what you want to authenticate with

lucid creek
mystic furnace
#

I just used the AbstractAuthenticationMiddleware to verify the JWT.
I'm not seeing that in the code you posted though

#

The JWT stuff only happens in the app that does the login stuff

lucid creek
#

I just recently added it. So, far it's working as intended tho

mystic furnace
#

Then maybe I'm not following what you're question is exactly 👀

lucid creek
#

Here's a sample diagram of what I want to achieve

mystic furnace
#

Well I can't say anything about your specific application, since I haven't seen its code, but using JWTs like this in general is pretty much a standard solution

lucid creek
#

got it, thanks

gloomy thistle
lucid creek
#

yes, sorry i forgot about this

#

!solve

native voidBOT
#

Marked as solved and closed the help forum!