For now I found two solutions to handle API keys by OpenLMIS:
1. Use access_token as a API key (most things are handled by Spring OAuth)
In this solution we will have a single entity in the reference data service - Service Account - which will contain fields like id, login and list of rights. The id field is required by database and the login field will be equal to access_token generated by the auth service which will be always valid (for now).
This solution if quite easy to introduce and don’t required too much work from us.
The problem I found with this solution is how service endpoints should handle new request type. Currently we only check if a request was sent by other service or by the end user. Probably, we will need to add a new if statement to check if the request was sent by an external service.
Also here we mix the meaning of access token because in some requests it will be treated as an access token and a API key in the same time. I am not sure if this is safe and correct approach.
2. Use custom header / request parameter (Some part will use Spring OAuth)
This solution requires more coding staff because we will need to create entities in reference-data and auth services (similar to user entities in those services), a custom filter to handle our custom header / parameter, probably custom authentication provider, and maybe some other additional classes.
In this solution an external service will use our custom header / parameter (probably X-API-KEY header or api_key parameter) to authenticate itself so our filter will check if there is a correct entry in the auth service, generate access token and add it to the request. In this case the external service will be authenticated with each request but only if the access token is expired. The access token part will be handled by Spring OAuth. Also if there will be an access token and the custom header / property the token will have higher priority than custom header.
Like I said this solution requires more coding but it would be easier to check a type of request by service endpoints because the principal field in Authentication will contain different values for different request types:
- client id -> service request
- username -> user request
- service account -> external service request
Also in this solution we don’t mix the meaning of access token. It will be always treated as an token that authenticate a user.
I would really like to hear what do you think about those propositions. If you think that there is a better approach which I don’t see then please let me know.
SolDevelo Sp. z o.o. [LLC] / www.soldevelo.com
Al. Zwycięstwa 96/98, 81-451, Gdynia, Poland
Phone: +48 58 782 45 40 / Fax: +48 58 782 45 41