Skip to content

Commit

Permalink
CORE-1027: added an endpoint that can be used to get authentication t…
Browse files Browse the repository at this point in the history
…okens from Keycloak
  • Loading branch information
slr71 committed Jun 18, 2020
1 parent a9003ee commit c39ccbc
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 13 deletions.
8 changes: 4 additions & 4 deletions resources/docs/get-token.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
This service allows users to obtain OAuth tokens for accessing other API endpoints. You must be logged in using HTTP
basic authorization to use this endpoint. This is the only endpoint that uses basic authorization. To log in, click the
Authorize button above, enter your username and password under `Basic authentication`, and click the Authorize button
underneath the password text box.
This service allows users to obtain OAuth or OIDC tokens for accessing other API endpoints. You must be logged in using
HTTP basic authorization to use this endpoint. The token endpoints are the only endpoints that use basic
authorization. To log in, click the Authorize button above, enter your username and password under `Basic
authentication`, and click the Authorize button underneath the password text box.

Once you have the access token, you can use it to authorize calls to other endpoints in the Swagger UI. First, remove
the basic authentication credentials by clicking the Authorize button above and clicking the Logout button in the `Basic
Expand Down
13 changes: 12 additions & 1 deletion src/terrain/clients/keycloak.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
(defn- keycloak-url
"Builds a Keycloak URL with the given path components."
[& components]
(str (apply curl/url (config/keycloak-base-uri) "auth" "realms" (config/keycloak-realm) components)))
(str (apply curl/url (config/keycloak-base-uri) "realms" (config/keycloak-realm) components)))

(defn get-oidc-certs
"Retrieves a list of active public certificates from Keycloak."
Expand All @@ -15,3 +15,14 @@
{:as :json})
:body
:keys))

(defn get-token
"Obtains an authorization token."
[username password]
(:body (http/post (keycloak-url "protocol" "openid-connect" "token")
{:form-params {:grant_type "password"
:client_id (config/keycloak-client-id)
:client_secret (config/keycloak-client-secret)
:username username
:password password}
:as :json})))
27 changes: 24 additions & 3 deletions src/terrain/routes/schemas/token.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
(ns terrain.routes.schemas.token
(:use [common-swagger-api.schema :only [describe]]
[schema.core :only [defschema]]))
[schema.core :only [defschema optional-key]]))

(defschema AccessTokenResponse
{:access_token (describe String "The access token")
:expires_in (describe String "The lifetime of the token in seconds")})
{:access_token
(describe String "The access token")

:expires_in
(describe Integer "The lifetime of the token in seconds")

(optional-key :refresh_expires_in)
(describe Integer "The lifetime of the refresh token in seconds")

(optional-key :refresh_token)
(describe String "The refresh token")

(optional-key :token_type)
(describe String "The type of the access token")

(optional-key :not-before-policy)
(describe Integer "The number of seconds before the token can be used")

(optional-key :session_state)
(describe String "A string representing the login state of the user")

(optional-key :scope)
(describe String "The scopes granted to the access token")})
16 changes: 14 additions & 2 deletions src/terrain/routes/token.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
(ns terrain.routes.token
(:use [common-swagger-api.schema :only [context routes GET]]
[terrain.routes.schemas.token]
[terrain.services.oauth :only [get-token]])
[terrain.services.oauth :as oauth])
(:require [common-swagger-api.routes])) ;; Required for :description-file

(defn token-routes
Expand All @@ -14,4 +14,16 @@
:summary "Obtain OAuth Tokens"
:return AccessTokenResponse
:description-file "docs/get-token.md"
(get-token authorization)))))
(oauth/get-token authorization))

(GET "/cas" [:as {{:strs [authorization]} :headers}]
:summary "Obtain OAuth Tokens"
:return AccessTokenResponse
:description-file "docs/get-token.md"
(oauth/get-cas-token authorization))

(GET "/keycloak" [:as {{:strs [authorization]} :headers}]
:summary "Obtain Keycloak OIDC Tokens"
:return AccessTokenResponse
:description-file "docs/get-token.md"
(oauth/get-keycloak-token authorization)))))
13 changes: 11 additions & 2 deletions src/terrain/services/oauth.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
(:require [clojure.data.codec.base64 :as base64]
[clojure.string :as string]
[ring.util.http-response :as http-response]
[terrain.clients.keycloak :as keycloak]
[terrain.clients.oauth :as client]
[terrain.util.service :as service]))

Expand All @@ -14,7 +15,15 @@
(String.)
(string/split #":" 2)))))

(defn get-token [authorization]
(defn get-cas-token [authorization]
(if-let [[username password] (get-basic-auth-credentials authorization)]
(http-response/ok (client/get-token username password))
(http-response/ok (update (client/get-token username password) :expires_in #(Integer/parseInt %)))
(http-response/unauthorized)))

(defn get-keycloak-token [authorization]
(if-let [[username password] (get-basic-auth-credentials authorization)]
(http-response/ok (keycloak/get-token username password))
(http-response/unauthorized)))

;; Make CAS the default identity provider for now.
(def get-token get-cas-token)
12 changes: 11 additions & 1 deletion src/terrain/util/config.clj
Original file line number Diff line number Diff line change
Expand Up @@ -521,13 +521,23 @@
(cc/defprop-optstr keycloak-base-uri
"The base URI for the Keycloak server."
[props config-valid configs]
"terrain.keycloak.base-uri" "https://kc.cyverse.org")
"terrain.keycloak.base-uri" "https://kc.cyverse.org/auth")

(cc/defprop-optstr keycloak-realm
"The Keycloak realm to use."
[props config-valid configs]
"terrain.keycloak.realm" "CyVerse")

(cc/defprop-str keycloak-client-id
"The Keycloak client ID to use."
[props config-valid configs]
"terrain.keycloak.client-id")

(cc/defprop-str keycloak-client-secret
"The keycloak client secret to use."
[props config-valid configs]
"terrain.keycloak.client-secret")

(cc/defprop-optstr dashboard-aggregator-url
"The URL to the dashboard-aggregator service."
[props config-valid configs]
Expand Down

0 comments on commit c39ccbc

Please sign in to comment.