|
| 1 | +# API Key Handler |
| 2 | + |
| 3 | +For some legacy applications to migrate from a monolithic gateway to the light-gateway without changing any code on the consumer application, we need to support the API Key authentication on the light-gateway (LG) or client-proxy (LCP). The consumer application sends the API key in a header to authenticate itself on the light-gateway. Then the light-gateway will retrieve a JWT token to access the downstream API. |
| 4 | + |
| 5 | +Only specific paths will have API Key set up, and the header name for each application might be different. To support all use cases, we add a list of maps to the configuration `apikey.yml` to `pathPrefixAuths` property. |
| 6 | + |
| 7 | +Each config item will have `pathPrefix`, `headerName`, and `apiKey`. The handler will try to match the path prefix first and then get the input API Key from the header. After comparing with the configured API Key, the handler will return either `ERR10075` API_KEY_MISMATCH or pass the control to the next handler in the chain. |
| 8 | + |
| 9 | +## Configuration |
| 10 | + |
| 11 | +The configuration is managed by `ApiKeyConfig` and corresponds to `apikey.yml` (or `apikey.json`/`apikey.properties`). |
| 12 | + |
| 13 | +### Configuration Properties |
| 14 | + |
| 15 | +| Property | Type | Default | Description | |
| 16 | +| :--- | :--- | :--- | :--- | |
| 17 | +| `enabled` | boolean | `false` | Enable ApiKey Authentication Handler. | |
| 18 | +| `hashEnabled` | boolean | `false` | If API key hash is enabled. The API key will be hashed with PBKDF2WithHmacSHA1 before it is stored in the config file. It is more secure than putting the clear text key into the config file. | |
| 19 | +| `pathPrefixAuths` | list | `null` | A list of mappings between path prefix and the api key parameters. | |
| 20 | + |
| 21 | +### Configuration Example (apikey.yml) |
| 22 | + |
| 23 | +```yaml |
| 24 | +# ApiKey Authentication Security Configuration for light-4j |
| 25 | +# Enable ApiKey Authentication Handler, default is false. |
| 26 | +enabled: ${apikey.enabled:false} |
| 27 | + |
| 28 | +# If API key hash is enabled. The API key will be hashed with PBKDF2WithHmacSHA1 before it is |
| 29 | +# stored in the config file. It is more secure than put the encrypted key into the config file. |
| 30 | +# The default value is false. If you want to enable it, you need to use the light-hash command line tool. |
| 31 | +hashEnabled: ${apikey.hashEnabled:false} |
| 32 | + |
| 33 | +# path prefix to the api key mapping. It is a list of map between the path prefix and the api key |
| 34 | +# for apikey authentication. In the handler, it loops through the list and find the matching path |
| 35 | +# prefix. Once found, it will check if the apikey is equal to allow the access or return an error. |
| 36 | +pathPrefixAuths: ${apikey.pathPrefixAuths:} |
| 37 | +``` |
| 38 | +
|
| 39 | +### Values Example (values.yml) |
| 40 | +
|
| 41 | +To enable the handler and configure paths, add the following to your `values.yml`: |
| 42 | + |
| 43 | +```yaml |
| 44 | +# apikey.yml |
| 45 | +apikey.enabled: true |
| 46 | +apikey.pathPrefixAuths: |
| 47 | + - pathPrefix: /test1 |
| 48 | + headerName: x-gateway-apikey |
| 49 | + apiKey: abcdefg |
| 50 | + - pathPrefix: /test2 |
| 51 | + headerName: x-apikey |
| 52 | + apiKey: mykey |
| 53 | +``` |
| 54 | + |
| 55 | +JSON format example for `pathPrefixAuths` (useful for config server): |
| 56 | + |
| 57 | +```json |
| 58 | +[{"pathPrefix":"/test1","headerName":"x-gateway-apikey","apiKey":"abcdefg"},{"pathPrefix":"/test2","headerName":"x-apikey","apiKey":"mykey"}] |
| 59 | +``` |
| 60 | + |
| 61 | +### Multiple Consumers for Same Path |
| 62 | + |
| 63 | +Most services will have multiple consumers, and each consumer might have its own API key for authentication. You can define multiple entries for the same path prefix: |
| 64 | + |
| 65 | +```yaml |
| 66 | +apikey.pathPrefixAuths: |
| 67 | + - pathPrefix: /test1 |
| 68 | + headerName: x-gateway-apikey |
| 69 | + apiKey: abcdefg |
| 70 | + # The same prefix has another apikey header and value. |
| 71 | + - pathPrefix: /test1 |
| 72 | + headerName: authorization |
| 73 | + apiKey: xyz |
| 74 | +``` |
| 75 | + |
| 76 | +## Security with Hash |
| 77 | + |
| 78 | +Storing API keys in clear text is only recommended for testing. For production, enable hashing: |
| 79 | + |
| 80 | +1. Enable hash in `values.yml`: |
| 81 | + ```yaml |
| 82 | + apikey.hashEnabled: true |
| 83 | + ``` |
| 84 | +2. Generate the hash of your API key using the [light-hash](https://github.com/networknt/light-hash) utility. |
| 85 | +3. Use the generated hash string as the `apiKey` value in your configuration. |
| 86 | + |
| 87 | +## Error Response |
| 88 | + |
| 89 | +If the request path matches a configured prefix but the API key verification fails, the handler returns error `ERR10075`. |
| 90 | + |
| 91 | +**Status Code**: 401 |
| 92 | +**Code**: ERR10075 |
| 93 | +**Message**: API_KEY_MISMATCH |
| 94 | +**Description**: APIKEY from header %s is not matched for request path prefix %s. |
| 95 | + |
| 96 | +To prevent leaking sensitive information, the expected apiKey from the config file is not revealed in the error message. |
| 97 | + |
| 98 | +## Usage |
| 99 | + |
| 100 | +Register the `ApiKeyHandler` in your `handler.yml` chain. |
| 101 | + |
| 102 | +```yaml |
| 103 | +handler.handlers: |
| 104 | + . |
| 105 | + - com.networknt.apikey.ApiKeyHandler@apikey |
| 106 | +
|
| 107 | +handler.chains.default: |
| 108 | + . |
| 109 | + - apikey |
| 110 | + . |
| 111 | +``` |
| 112 | + |
| 113 | +If you are using the Unified Security Handler, you can integrate the API Key handler there as well to support multiple authentication methods (ApiKey, Basic, OAuth2, SWT) simultaneously. |
0 commit comments