API for secured requests.
The authentication API is compatible with the following standards:
https://api.ka3.uni-koeln.de/
https://api.ka3.uni-koeln.de/login
https://api.ka3.uni-koeln.de/validate
https://ka3.uni-koeln.de
https://ka3.uni-koeln.de/authentication/login
https://ka3.uni-koeln.de/saml/logout
https://ka3.uni-koeln.de/authentication/token
Users register via a SAML service provider: /account/index.
The following SAML attributes are stored locally during registration:
If a home institution does not provide these required attributes, registration fails.
Authentication for non-user-driven clients.
POST {scheme}://{server}/login
Example request:
POST /api.ka3.uni-koeln.de/login HTTP/1.1 Host: api.ka3.uni-koeln.de { username: "user@institution.com", password: "123456" }
username
and password
.username
is the value of
eduPersonPrincipalName
as set
during registration.password
can be set here:
/account/resetPassword. It is different from the SAML single sign-on
password.Response body is a JSON Web Token as described in RFC 6750.
Example response body:
{ "username": "user@institution.com", "roles": [ROLE_MANAGER], "expires_in": 3600, "token_type": "Bearer", "refresh_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00i", "access_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00if" }
POST {scheme}://{server}/validate
Example Request:
POST /api.ka3.uni-koeln.de/validate HTTP/1.1 Host: api.ka3.uni-koeln.de Authorization: Bearer eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00if
Returns HTTP 200 if the token is still valid, HTTP 401 otherwise.
A logout request is not needed for headless authentication, as no state is kept in the server. Just remove the token from the client and let the token expire.
SAML Single Sign-On authentication for user-driven clients.
Frontend authentication makes use of a secure session between a user client (SPA, Native App) and a SAML service provider in order to provide user clients JSON Web Tokens for REST API access.
GET {scheme}://{server}/authentication/login?origin={frontend}[&messageId]
Establishes a session between a user client and a SAML service provider and provides a valid access token for REST API access.
See: https://iiif.io/api/auth/1.0/#login-interaction-pattern
window.open("https://ka3.uni-koeln.de/authentication/login?origin=https://frontend.example.com&messageId")
. The
messageId
parameter prompts the server to respond with a web page instead of JSON.https://ka3.uni-koeln.de/samlDiscover
.https://ka3.uni-koeln.de/authentication/login?origin=https://frontend.example.com&messageId
, which is a HTML page thanks to the
messageId
parameter. The HTML page contains the following HTML / JavaScript snippet:
<div id="token" data-token="{"access_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00if", ...}"></div> <script> document.addEventListener("DOMContentLoaded", function() { let token = document.getElementById("token").dataset.token; window.opener.postMessage(JSON.parse(token), "https://frontend.example.com"); }); </script>
window.opener.postMessage(JSON.parse(token), "https://frontend.example.com")
. Because of the Same-Origin-Policy, this
only works if the origin
parameter was set correctly in step 2.window.addEventListener("message", function(event) { //event.data contains the JWT }
event.data
contains the access token. After the "message" event is completed, the frontend
continues in its individual way by storing the token in the session storage, for example. See below for a
minimal example.GET {scheme}://{server}/authentication/token?origin={frontend}[&messageId]
Refreshes the session between the user client and the SAML service provider and sends the actual access token or a new access token, if the old has become invalid.
See: https://iiif.io/api/auth/1.0/#access-token-service
<iframe id="tokenFrame" src="https://ka3.uni-koeln.de/authentication/token?origin=https://frontend.example.com&messageId"></iframe> <script> setTimeout(function() { document.getElementById("tokenFrame").src = null; document.getElementById("tokenFrame").src = "https://ka3.uni-koeln.de/authentication/token?origin=https://frontend.example.com&messageId" }, 20 * 60 * 1000); </script>
GET {scheme}://{server}/saml/logout
Closes the session between the user client and the SAML service provider. In order to complete the logout, user clients should delete the local access token.
See: https://iiif.io/api/auth/1.0/#logout-service
this.logoutWindow = window.open("https://ka3.uni-koeln.de/saml/logout")
.this.logoutWindow.close()
.{ "access_token": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00if", "token_type": "Bearer", "expires_in": "3600", "session_expires_in": "1800", "username": "gtest@uni-koeln.de", "cn": "Grails Test", "mail": "gtest@uni-koeln.de", "roles": ["ROLE_MANAGER", "ROLE_DEPOSITOR"] }
The frontend JWT is slightly different from the headless JWT:
cn
and a mail address
mail
.refresh_token
available. Tokens can only be refreshed by
means of the Refresh Session Procedure.session_expires_in
: when to refresh the session the latest.<button id="loginButton">Login</button> <button id="logoutButton" style="display:none;">Logout</button> <div id="tokenView"></div> <iframe id="tokenFrame" src="" style="display:none"></iframe> <script> const self = this; function refreshToken() { let tokenFrame = document.getElementById("tokenFrame"); tokenFrame.src = null; tokenFrame.src = "https://ka3.uni-koeln.de/authentication/token?messageId&origin=" + window.location.origin; } function refreshView() { if (sessionStorage.getItem("JWT")) { document.getElementById("loginButton").style.display = "none"; document.getElementById("logoutButton").style.display = ""; document.getElementById("tokenView").innerText = window.sessionStorage.getItem("JWT"); } else { document.getElementById("loginButton").style.display = ""; document.getElementById("logoutButton").style.display = "none"; document.getElementById("tokenView").innerText = ""; } } refreshView(); document.getElementById("loginButton").addEventListener("click", function() { self.loginWindow = window.open("https://ka3.uni-koeln.de/authentication/login?messageId&origin=" + window.location.origin); }); document.getElementById("logoutButton").addEventListener("click", function() { self.logoutWindow = window.open("https://ka3.uni-koeln.de/saml/logout"); window.setTimeout(function() { refreshToken(); }, 1000); }); window.addEventListener("message", function(event) { if (event.data.hasOwnProperty("access_token")) { //login procedure or refresh session procedure return a valid //access token (session is valid) sessionStorage.setItem("JWT", JSON.stringify(event.data)); if (self.loginWindow) { //login procedure self.loginWindow.close(); } refreshView(); } else { //refresh session procedure does not return a access token (session is closed) sessionStorage.removeItem("JWT"); if (self.logoutWindow) { //logout procedure self.logoutWindow.close(); } refreshView(); } }); window.setInterval(function() { //refresh the session every 20 minutes refreshToken(); }, 20 * 60 * 1000); </script>
The preferred way to request a secured resource with ajax is to send the access_token
in the HTTP
Authorization
header:
GET /api.ka3.uni-koeln.de/deposit/a5-1 HTTP/1.1 Host: api.ka3.uni-koeln.de Authorization: Bearer eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00if
See: https://tools.ietf.org/html/rfc6750#section-2.1
Alternatively, the access token can be sent in a query string parameter named
access_token
:
GET /api.ka3.uni-koeln.de/deposit/a5-1?access_token=eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00if HTTP/1.1 Host: api.ka3.uni-koeln.de
See: https://tools.ietf.org/html/rfc6750#section-2.3
This is especially useful for HTML object rendering and streaming.