Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra validation of JWT with fingerprints #460

Closed
dpalmasan opened this issue Apr 3, 2022 · 2 comments
Closed

Extra validation of JWT with fingerprints #460

dpalmasan opened this issue Apr 3, 2022 · 2 comments

Comments

@dpalmasan
Copy link

Describe what are you trying to do

In my setup I have a microservice which issues JWT to users. I already tested JWT validation with KrakenD and it works fine. However, I would also like to implement OWASP recomendations for JWT, in my use case I have the following:

  1. I create a unique token and use it as a fingerprint
  2. This token is added to a cookie (Http Only, same site, Secure)
  3. I also add a hash of the token (SHA256) to the JWT claims

Then I just compare the values as an extra validation of the JWK token. Since I have multiple services (implemented in other languages), it will make the validation cumbersome if I move this logic outside KrakenD request processing. What would be the simplest approach to implement this flow on KrakenD side?

Your configuration file
My krakend.json:

{
    "version": 3,
    "extra_config": {
        "github_com/devopsfaith/krakend-gologging": {
            "level": "DEBUG",
            "prefix": "[KRAKEND]",
            "syslog": false,
            "stdout": true,
            "format": "logstash"
        },
        "github_com/devopsfaith/krakend-logstash": {
            "enabled": true
        }
    },
    "plugin": {
        "pattern": ".so",
        "folder": "./jwt_revoked_checker"
    },
    "timeout": "15s",
    "cache_ttl": "300s",
    "output_encoding": "json",
    "name": "api-gateway",
    "port": 8080,
    "endpoints": [
        {
            "endpoint": "/login",
            "method": "POST",
            "output_encoding": "no-op",
            "extra_config": {
                "github.com/devopsfaith/krakend-ratelimit/juju/router": {
                    "maxRate": 0,
                    "clientMaxRate": 30,
                    "strategy": "ip"
                }
            },
            "backend": [
                {
                    "url_pattern": "/session/jwt",
                    "encoding": "no-op",
                    "sd": "static",
                    "method": "POST",
                    "host": [
                        "localhost:4001"
                    ],
                    "disable_host_sanitize": false
                }
            ]
        },
        {
            "endpoint": "/refresh",
            "input_headers": [
                "Cookie",
                "Authorization",
                "Content-Type"
            ],
            "method": "POST",
            "output_encoding": "no-op",
            "extra_config": {
                "github.com/devopsfaith/krakend-ratelimit/juju/router": {
                    "maxRate": 0,
                    "clientMaxRate": 30,
                    "strategy": "ip"
                },
                "plugin/req-resp-modifier": {
                    "name": [
                        "auth-access-check-request",
                        "auth-access-check-response"
                    ]
                }
            },
            "backend": [
                {
                    "url_pattern": "/session/refresh",
                    "encoding": "no-op",
                    "sd": "static",
                    "method": "POST",
                    "host": [
                        "localhost:4001"
                    ],
                    "disable_host_sanitize": false
                }
            ]
        },
        {
            "endpoint": "/register",
            "method": "POST",
            "output_encoding": "no-op",
            "extra_config": {
                "github.com/devopsfaith/krakend-ratelimit/juju/router": {
                    "maxRate": 0,
                    "clientMaxRate": 30,
                    "strategy": "ip"
                }
            },
            "backend": [
                {
                    "url_pattern": "/session/register",
                    "encoding": "no-op",
                    "sd": "static",
                    "method": "POST",
                    "host": [
                        "localhost:4001"
                    ],
                    "disable_host_sanitize": false
                }
            ]
        },
        {
            "endpoint": "/posts",
            "input_headers": [
                "Cookie",
                "Authorization",
                "Content-Type"
            ],
            "method": "POST",
            "output_encoding": "json",
            "extra_config": {
                "github.com/devopsfaith/krakend-ratelimit/juju/router": {
                    "maxRate": 0,
                    "clientMaxRate": 3,
                    "strategy": "ip"
                },
                "auth/validator": {
                    "alg": "RS256",
                    "jwk_local_path": "./jwks.json",
                    "cache": false,
                    "roles_key": "role",
                    "roles_key_is_nested": false,
                    "roles": [
                        "regular",
                        "admin"
                    ],
                    "disable_jwk_security": true,
                    "operation_debug": true
                },
                "plugin/req-resp-modifier": {
                    "name": [
                        "auth-access-check-request",
                        "auth-access-check-response"
                    ]
                }
            },
            "backend": [
                {
                    "url_pattern": "/posts",
                    "encoding": "json",
                    "sd": "static",
                    "method": "POST",
                    "disable_host_sanitize": false,
                    "host": [
                        "localhost:8000"
                    ],
                    "extra_config": {
                        "plugin/req-resp-modifier": {
                            "name": [
                                "auth-access-check-request"
                            ]
                        }
                    }
                }
            ]
        },
        {
            "endpoint": "/posts",
            "headers_to_pass": [
                "Cookie"
            ],
            "method": "GET",
            "output_encoding": "json",
            "extra_config": {
                "github.com/devopsfaith/krakend-ratelimit/juju/router": {
                    "maxRate": 0,
                    "clientMaxRate": 3,
                    "strategy": "ip"
                },
                "auth/validator": {
                    "alg": "RS256",
                    "jwk_local_path": "./jwks.json",
                    "cache": false,
                    "roles_key": "role",
                    "roles_key_is_nested": false,
                    "roles": [
                        "regular",
                        "admin"
                    ],
                    "cookie_key": "access_token",
                    "disable_jwk_security": true,
                    "operation_debug": true
                }
            },
            "backend": [
                {
                    "url_pattern": "/posts",
                    "encoding": "json",
                    "sd": "static",
                    "method": "GET",
                    "disable_host_sanitize": false,
                    "host": [
                        "localhost:8000"
                    ]
                }
            ]
        },
        {
            "endpoint": "/posts/{post_id}",
            "headers_to_pass": [
                "Cookie"
            ],
            "method": "GET",
            "output_encoding": "json",
            "extra_config": {
                "github.com/devopsfaith/krakend-ratelimit/juju/router": {
                    "maxRate": 0,
                    "clientMaxRate": 3,
                    "strategy": "ip"
                },
                "github.com/devopsfaith/krakend/proxy": {
                    "sequential": true
                },
                "auth/validator": {
                    "alg": "RS256",
                    "jwk_local_path": "./jwks.json",
                    "cache": false,
                    "roles_key": "role",
                    "roles_key_is_nested": false,
                    "roles": [
                        "regular",
                        "admin"
                    ],
                    "cookie_key": "access_token",
                    "disable_jwk_security": true,
                    "operation_debug": true
                }
            },
            "backend": [
                {
                    "url_pattern": "/posts/{post_id}",
                    "encoding": "json",
                    "sd": "static",
                    "method": "GET",
                    "disable_host_sanitize": false,
                    "host": [
                        "localhost:8000"
                    ]
                },
                {
                    "url_pattern": "/metrics?id={resp0__id}&text={resp0_body}",
                    "encoding": "json",
                    "sd": "static",
                    "method": "GET",
                    "host": [
                        "localhost:6000"
                    ],
                    "disable_host_sanitize": false,
                    "is_collection": false
                }
            ]
        }
    ]
}
@kpacha
Copy link
Member

kpacha commented Jun 16, 2022

I think you could add the extra validation with a request modifier plugin (https://www.krakend.io/docs/extending/plugin-modifiers/). if you extract the claim with the fingerprint (https://www.krakend.io/docs/authorization/jwt-validation/#propagate-jwt-claims-as-request-headers) and allow the cookie header and the one with the extracted claim to pass, you can calculate the fingerprint of the cookie and compare it with the extracted claim. if they match, do nothing. if they don't match, return an error with the 401

@github-actions
Copy link

This issue was marked as resolved a long time ago and now has been automatically locked as there has not been any recent activity after it. You can still open a new issue and reference this link.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants