hurl icon indicating copy to clipboard operation
hurl copied to clipboard

JWT Authentication

Open Aditeya opened this issue 1 year ago • 5 comments

Problem to solve

My endpoint is authenticated using a JWT. Endpoint 1 has JWT type A and Endpoint 2 has JWT type B. I want to create JWT type B with data from Endpoint 1 to use Endpoint 2.

Proposal

I think a function that takes the a JWT header(JSON), Payload(also JSON) & signature(string or var) to create a JWT token would be perfect.

Additional context and resources

I'd be using this for CI/CD integration and it would be good away to create tokens & test a certain flow properly.

Tasks to complete

  • [ ] TODO

Aditeya avatar Dec 04 '23 09:12 Aditeya

Hi @Aditeya

In your use case, the JWT token is given by an Authentification server, then pass as header ? Do I miss something if your current workflow looks like this :

# Get an authorization token for A 
POST https://authserver.com
{
 "username": "aaa",
 "password": "aaa"
}
HTTP 200
[Captures]
jwt_token_a: jsonpath "$.access_token"

# Request can be now be played with JWT A token
GET https://my-server.com
Authorization: bearer {{jwt_token_a}}
HTTP 200

# Get an authorization token for B
POST https://authserver.com
{
 "username": "bbb",
 "password": "bbb"
}
HTTP 200
[Captures]
jwt_token_b: jsonpath "$.access_token"

# Request can be now be played with JWT B token
GET https://my-server.com
Authorization: bearer {{jwt_token_b}}
HTTP 200

Would you be able to give us more details in term of workflow, and what do you imagine with a Hurl file (with potential new syntax)?

jcamiel avatar Dec 04 '23 12:12 jcamiel

Hi @jcamiel Yes it looks like that, except I want a function to transform the capture.

I'd imagine the function to look like JWT(header: Json/Enum, payload: Json: signature: key) and it would pretty much function like in the jwt crate. I think header could also have some predefined options like an enum.

POST http://localhost:8080/teamspace
Authorization: Bearer {{env_token}}
{
	"name": "test teamspace"
}
HTTP 200
[Captures]
teamspace_userID_token: JWT(
	{"alg": "HS256", "typ": "JWT"},
	{
		"teamspace_id": jsonpath "$.teamspace_id"
		"public_teamspace_id": {{ptid}}
		"teamspace_user_id": {{from_anther_request_capture}}
	},
	{{key_from_env}}
)

DELETE http://localhost:8080/teamspace
Authorization: Bearer {{teamspace_userID_token}}

HTTP 200

Aditeya avatar Dec 05 '23 04:12 Aditeya

I have the same requirement. As a start, I'd even be happy with something simpler than that:

OST http://localhost:8080/teamspace
Authorization: Bearer {{env_token}}
{
	"name": "test teamspace"
}
HTTP 200
[Captures]
teamspace_user_id: jwtpath "$.accessToken.teamspace_id"

DELETE http://localhost:8080/teamspace
Authorization: Bearer {{teamspace_user_id}}

HTTP 200

What I'm suggesting is a bit simpler, but it would get the job done for extracting claims. A new helper method called jwtpath (like jsonpath) unpacks the body using the JWT crate, and extracts the claim out of the JSON body of the JWT using jsonpath syntax.

marc0der avatar Jan 04 '24 10:01 marc0der

Hi @jcamiel Yes it looks like that, except I want a function to transform the capture.

I'd imagine the function to look like JWT(header: Json/Enum, payload: Json: signature: key) and it would pretty much function like in the jwt crate. I think header could also have some predefined options like an enum.

POST http://localhost:8080/teamspace
Authorization: Bearer {{env_token}}
{
	"name": "test teamspace"
}
HTTP 200
[Captures]
teamspace_userID_token: JWT(
	{"alg": "HS256", "typ": "JWT"},
	{
		"teamspace_id": jsonpath "$.teamspace_id"
		"public_teamspace_id": {{ptid}}
		"teamspace_user_id": {{from_anther_request_capture}}
	},
	{{key_from_env}}
)

DELETE http://localhost:8080/teamspace
Authorization: Bearer {{teamspace_userID_token}}

HTTP 200

I too have a use case that would majorly benefit from an implementation like this.

Ghxst avatar Jan 20 '24 15:01 Ghxst

I have the use case too but:

Simple

I use jwt-cli with awk and a hurl variable file. Like this you can craft a token. In the server also implement a way to use symmetric keys in local. (rest of auth stays the same, only the signature check will differ)

Here is a public example of the token creation: https://github.com/SilenLoc/baselOne2024/blob/main/showcases/springboot/token_creation/justfile

  • Craft a token

  • With jwt-cli | jq I can take out the values of the payload I like and set them with awk inside the variable file.

  • Run the tests.

Actual auth server

If it an actual authorization server I do the same but instead of crafting a token:

  • Run a simple curl command, then set the token var inside of variable file with awk.

  • Again use jwt-cli | jq to pick the values, set them with awk in the variable file.

  • Run the tests.

Multiple tokens

If this does not suffice, lets say we want to test for multiple tokens you may need to split the tests into multiple directories. Then do the same thing but with three time with diffrent parameters.

Local proxy method

Create a small proxy which does the heavy lifting for you:

  • create and enpoint which fetches you a token
  • split the token and retun a json payload
  • in hurl, ask the server, capture the values
  • run the tests (where you use the valuse from the capture)

You may even cache the token on the local proxy.

Of course I would not need all this if we would have a "function" for it :)

SilenLoc avatar Jun 07 '24 10:06 SilenLoc