Secret Store
Why?
Ideally, every client communicating with a service protected by an OAuth solution would use OAuth when sending the requests. Unfortunately, that’s not always possible, feasible or even desirable. For instance, on batch jobs or daemons, the logic of storing an OAuth Offline Token and getting an OAuth Access Token based on the Offline Token might be too much for a simple script that would otherwise be very simple. Or even, your client might be a legacy application, where no change in the code would be allowed (or desirable). There are also situations where the client is not powerful enough or might live in a location far from the Auth server, making it unfeasible store the logic there or to make an extra HTTP round trip just to get an Access Token.
For those cases, the Secret Store exists: the Offline token is created on Keycloak via an user interaction and an opaque token backed by this Offline token is generated on the Secret Store. In return, the Secret Store provides a key and secret, that references this Offline token. The clients use this key/secret pair and send them as standard HTTP Basic Authentication to your target service, and the filter (or proxy) is responsible for handling the OAuth logic of converting an Offline Token into an Access Token. It also handles the storage, creation and caching of such tokens.
About Secret Store
The project is divided into several modules. More information about the individual modules can be found in the respective module’s README files.
-
secret-store: the REST backend for generating key/secret tokens backed by Keycloak Offline tokens
-
secret-store-api: components that are intended to be consumed by other Java Enterprise Web Applications
-
feature-pack: Generates a feature pack for Wildfly. Intended to be consumed only by the integration tests
-
feature-pack-resources: Extra resources needed by the final distribution
-
integration-tests: A set of integration tests
-
proxy: HTTP Proxy which replaces key/secret by OAuth Tokens before forwarding the request to the target server.
-
undertow-filter: Undertow Filter which replaces key/secret by OAuth tokens on incoming requests.
-
examples: Shows how to use the secret store by embedding a filter or by deploying a proxy.
Basic usage
The Secret Store has the following main components:
-
Backend, protected via the Keycloak Wildfly Adapter
-
Undertow Filter
-
Proxy
A token is created when an user reaches the path /secret-store/v1/tokens/create
via GET (or passing the username and password as Basic authentication via POST) and stored into a Cassandra data store:
$ curl -u jdoe:password -H 'Accept: application/json' http://localhost:8080/secret-store/v1/tokens/create -X POST
{"key":"07579322-a915-4b1c-89b3-39b13b013193","secret":"55f32d90fd821c3d198e11ec05d896e4"}
If the target application is using the Undertow Filter, then the client application can start using this token as username/password when calling the target application:
$ curl -u jdoe:password -H 'Accept: application/json' http://localhost:8080/hawkular/accounts/personas/current
{"id":"28026b36-8fe4-4332-84c8-524e173a68bf","createdAt":"2015-12-18T14:19:13.816Z","updatedAt":"2015-12-18T14:19:13.816Z","name":"John Doe","idAsUUID":"28026b36-8fe4-4332-84c8-524e173a68bf"}
$ curl -u 07579322-a915-4b1c-89b3-39b13b013193:55f32d90fd821c3d198e11ec05d896e4 -H 'Accept: application/json' http://localhost:8080/hawkular/accounts/personas/current
{"id":"28026b36-8fe4-4332-84c8-524e173a68bf","createdAt":"2015-12-18T14:19:13.816Z","updatedAt":"2015-12-18T14:19:13.816Z","name":"John Doe","idAsUUID":"28026b36-8fe4-4332-84c8-524e173a68bf"}
Similarly, the client application can send the token to the target application when using the proxy. The proxy will take care of converting the key/secret into a bearer token, so that the target application sees only this OAuth token. In the following example, the proxy is running on localhost:8081:
$ curl -x http://localhost:8081 -u 07579322-a915-4b1c-89b3-39b13b013193:55f32d90fd821c3d198e11ec05d896e4 -H 'Accept: application/json' http://localhost:8080/hawkular/accounts/personas/current
{"id":"28026b36-8fe4-4332-84c8-524e173a68bf","createdAt":"2015-12-18T14:19:13.816Z","updatedAt":"2015-12-18T14:19:13.816Z","name":"John Doe","idAsUUID":"28026b36-8fe4-4332-84c8-524e173a68bf"}
Once a token has been generated, a QR Code can be generated with the key, secret and expiration date. For that, just display the following URL as a PNG image to the authenticated user: /secret-store/qrcode?tokenId=key&size=50
, replacing key
by the actual Token key. The size
parameter is optional, and shows a 250x250 PNG image by default.
Refer to the Backend’s, Filter’s and/or to the Proxy’s README for more details on how to use it.
What’s this Hawkular thing I see in the code?
Hawkular is a an opensource monitoring solution sponsored by Red Hat. Originally, the Secret Store was developed to suit the needs of that project. It was later split, so that Secret Store could be reused outside of the Hawkular context. So, most of the references to Hawkular (and Hawkular Accounts) were stripped, but some facilities were kept, such as the embedded Cassandra and some Cassandra-related common utilities. This does not mean, however, that you need Hawkular to build, use or consume the Secret Store.
How to build Secret Store from source
The API and backend can be build as a regular Maven project:
$ mvn clean install
Releasing
To perform a release of Secret Store, you’ll need push permissions to the GitHub repository and execute the following:
mvn clean
mvn release:prepare release:perform
And accept all the default values (for versions and tags).
License
Secret Store is released under Apache License, Version 2.0 as described in the LICENSE document
Copyright 2015 Red Hat, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.