Authentication#
Some functionality of the freva-rest API and the client library is only accessible after successful authentication. This authentication is realised with OAuth2 token creation. You can create new access and refresh tokens. Refresh tokens can be used to create new access tokens without needing to log in via username and password, thereby minimising the risk of exposing login credentials. Bear in mind that both login and refresh tokens have a limited lifetime.
Generally speaking, you have three options to interact with the authorization system:
via the REST API
/api/freva-nextgen/auth/v2
endpointsvia the
freva_client.authenticate()
functionvia the
freva-client auth
command-line interface
Warning
Starting with version 2506.0.0, the password grant type is no longer supported.
Authentication must now be performed using the authorization code flow. Unless you want to setup a service provider, we advice against using the restAPI endpoints for authentication.
Using the restAPI endpoints#
The API supports token-based authentication using OAuth2. To obtain an access
token, clients can use the /api/freva-nextgen/auth/v2/token
endpoint by
providing valid username and password credentials. The access token should
then be included in the authorization header for secured endpoints.
- POST /api/freva-nextgen/auth/v2/token#
Create an new login token from a username and password. You should either set a username and password or an existing refresh token. You can also set the client_id. Client id’s are configured to gain access, specific access for certain users. If you don’t set the client_id, the default id will be chosen.
- Form Parameters:
code – The code received as part of the OAuth2 authorization code flow
redirect_uri – The URI to which the authorization server will redirect the user after authentication. It must match one of the URIs registered with the OAuth2 provider
refresh-token – The refresh token that is used to create a new token the refresh token can be used instead of authorizing via user creentials.
client_id – The unique identifier for your application used to request an OAuth2 access token from the authentication server, this form parameter is optional.
- Status Codes:
200 OK – no error
401 Unauthorized – unauthorized
- Response Headers:
Content-Type –
application/json
: access and refresh token.
Example Request#
POST /api/freva-nextgen/auth/v2/token HTTP/1.1 host: www.freva.dkrz.de { "refresh-token": "my-token", }
Example Request#
HTTP/1.1 200 OK Content-Type: application/json { "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6.." "token_type": "Bearer", "expires": 1722874908, "refresh_token": "eyJhbGciOiJIUzUxMiIsInR5cCIgOiAiSldUIiwia2lkIi.." "refresh_expires": 1722876408, "scope": "profile email address", }
Code examples#
Below you can find example usages of this request in different scripting and programming languages
curl -X POST https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/token \ -d "username=janedoe" \ -d "password=janedoe123"
import requests response = requests.post( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/token", data={"refresh-token": "mytoken"} ) token_data = response.json()
library(httr) url <- "https://freva.dkrz.de/api/freva-nextgen/auth/v2/token" response <- POST( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/token", body = setNames(list("mytoken"), "refresh-token"), encode = "form" ) token_data <- content(response, "parsed")
using HTTP using JSON response = HTTP.POST( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/token", body = Dict("refresh-token" => "mytoken") ) token_data = JSON.parse(String(response.body))
#include <stdio.h> #include <curl/curl.h> int main() { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); curl_easy_setopt(curl, CURLOPT_URL, "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/token"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "refresh-token=mytoken"); res = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
—
- GET /api/freva-nextgen/auth/v2/status#
Check the status of an access token.
- Request Headers:
Authorization – The OAuth2 access token
- Status Codes:
200 OK – no error
401 Unauthorized – unauthorized
- Response Headers:
Content-Type –
application/json
: access and refresh token.
Example Request#
POST /api/freva-nextgen/auth/v2/status HTTP/1.1 host: www.freva.dkrz.de Authorization: Bearer your_access_token
Example Request#
HTTP/1.1 200 OK Content-Type: application/json { "sub": "648692af-aaed-4f82-9f74-2d6baf96f5ea", "exp": 1719261824, "email": "jane@example.com" }
Code examples#
Below you can find example usages of this request in different scripting and programming languages
curl -X GET https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/status \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
import requests response = requests.get( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/status", headers={"Authorization": "Bearer YOUR_ACCESS_TOKEN"} ) token_data = response.json()
library(httr) response <- GET( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/status", add_headers(Authorization = paste("Bearer", "YOUR_ACCESS_TOKEN")) ) token_data <- content(response, "parsed")
using HTTP using JSON response = HTTP.get( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/status", headers = Dict("Authorization" => "Bearer YOUR_ACCESS_TOKEN") ) token_data = JSON.parse(String(response.body))
#include <stdio.h> #include <curl/curl.h> int main() { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer YOUR_ACCESS_TOKEN"); curl_easy_setopt(curl, CURLOPT_URL, "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/status"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
—
- GET /api/freva-nextgen/auth/v2/userinfo#
Get userinfo for the current token.
- Request Headers:
Authorization – The OAuth2 access token
- Status Codes:
200 OK – no error
401 Unauthorized – unauthorized
- Response Headers:
Content-Type –
application/json
: access and refresh token.
Example Request#
POST /api/freva-nextgen/auth/v2/userinfo HTTP/1.1 host: www.freva.dkrz.de Authorization: Bearer your_access_token
Example Request#
HTTP/1.1 200 OK Content-Type: application/json { "username": "janedoe", "first_name": "Jane", "last_name": "Doe", "email": "jane@example.com" "home": "" "is_guest": true }
Code examples#
Below you can find example usages of this request in different scripting and programming languages
curl -X GET https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/userinfo \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
import requests response = requests.get( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/userinfo", headers={"Authorization": "Bearer YOUR_ACCESS_TOKEN"} ) token_data = response.json()
library(httr) response <- GET( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/userinfo", add_headers(Authorization = paste("Bearer", "YOUR_ACCESS_TOKEN")) ) token_data <- content(response, "parsed")
using HTTP using JSON response = HTTP.get( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/userinfo", headers = Dict("Authorization" => "Bearer YOUR_ACCESS_TOKEN") ) token_data = JSON.parse(String(response.body))
#include <stdio.h> #include <curl/curl.h> int main() { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer YOUR_ACCESS_TOKEN"); curl_easy_setopt(curl, CURLOPT_URL, "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/userinfo"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
—
- GET /api/freva-nextgen/auth/v2/systemuser#
Get system information for the user in possession of the oauth token.
- Request Headers:
Authorization – The OAuth2 access token
- Status Codes:
200 OK – no error
401 Unauthorized – unauthorized
- Response Headers:
Content-Type –
application/json
: access and refresh token.
Example Request#
POST /api/freva-nextgen/auth/v2/systemuser HTTP/1.1 host: www.freva.dkrz.de Authorization: Bearer your_access_token
Example Request#
HTTP/1.1 200 OK Content-Type: application/json { "pw_name": "janedoe", "pw_passwd": "\*", "pw_uid": 1000, "pw_gid": 1001 "pw_gecos": "Jane Doe", "pw_dir": "/home/jane", "pw_shell": "/bin/zsh" }
Code examples#
Below you can find example usages of this request in different scripting and programming languages
curl -X GET https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/systemuser \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
import requests response = requests.get( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/systemuser", headers={"Authorization": "Bearer YOUR_ACCESS_TOKEN"} ) token_data = response.json()
library(httr) response <- GET( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/systemuser", add_headers(Authorization = paste("Bearer", "YOUR_ACCESS_TOKEN")) ) token_data <- content(response, "parsed")
using HTTP using JSON response = HTTP.get( "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/systemuser", headers = Dict("Authorization" => "Bearer YOUR_ACCESS_TOKEN") ) token_data = JSON.parse(String(response.body))
#include <stdio.h> #include <curl/curl.h> int main() { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if(curl) { struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Authorization: Bearer YOUR_ACCESS_TOKEN"); curl_easy_setopt(curl, CURLOPT_URL, "https://www.freva.dkrz.de/api/freva-nextgen/auth/v2/userinfo"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); res = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); return 0; }
—
Using the freva-client python library#
The freva-client python library offers a very simple interface to interact with the authentication system.
Client software freva evaluation system framework (freva):
Freva, the free evaluation system framework, is a data search and analysis platform developed by the atmospheric science community for the atmospheric science community. With help of Freva researchers can:
quickly and intuitively search for data stored at typical data centers that host many datasets.
create a common interface for user defined data analysis tools.
apply data analysis tools in a reproducible manner.
The code described here is currently in testing phase. The client and server library described in the documentation only support searching for data. If you need to apply data analysis plugins, please visit the
- freva_client.authenticate(*, token_file: str | Path | None = None, host: str | None = None, force: bool = False) Token #
Authenticate to the host.
This method generates a new access token that should be used for restricted methods.
- Parameters:
refresh_token (str, optional) – Instead of setting a password, you can set a refresh token to refresh the access token. This is recommended for non-interactive environments.
host (str, optional) – The hostname of the REST server.
force (bool, default: False) – Force token recreation, even if current token is still valid.
- Returns:
Token
- Return type:
The authentication token.
Examples
Interactive authentication:
from freva_client import authenticate token = authenticate() print(token)
Batch mode authentication with a refresh token:
from freva_client import authenticate token = authenticate(token_file="~/.freva-login-token.json")
Using the command line interface#
Token creation and refreshing can also be achieved with help of the auth
sub command of the command line interface
freva-client auth --help
Results
Usage: freva-client auth [OPTIONS]
Create OAuth2 access and refresh token.
Options:
--host TEXT Set the hostname of the databrowser, if not set (default)
the hostname is read from a config file
--token-file TEXT Instead of authenticating via code based authentication
flow you can set the path to the json file that contains
a `refresh token` containing a refresh_token key.
-f, --force Force token recreation, even if current token is still
valid.
-v Increase verbosity [default: 0]
-V, --version Show version an exit
--help Show this message and exit.
You can create a token using your user name and password. For security reasons you can not pass your password as an argument to the command line interface. This means that you can only create a new token with help of a valid refresh token in a non-interactive session. Such as a batch job.
Therefore you want to store your token data securely in a file, and use the refresh token to create new tokens:
freva-client auth > ~/.mytoken.json
chmod 600 ~/.mytoken.json
Later you can use the jq json command line parser to read the refresh token from and use it to create new access tokens.
freva-client auth --token-file ~/.mytoken.json > ~/.mytoken.json
Warning
Avoid storing access tokens insecurely. Access tokens are sensitive and should be treated like passwords. Do not store them in publicly readable plaintext or in code repositories. Instead:
Use environment variables or secure storage (e.g.
.netrc
, OS keychains).Rotate and expire tokens regularly if implementing long-running SPs.
Notes on Code-Based Auth Flow#
Code-based authentication is the only supported method since
version 2505.1.0
. It follows the OAuth2 Authorization Code Flow and is
suitable for both end users and Service Provider (SP) integrations.
However, there are important guidelines and limitations you should be aware of.
🔒 Do not call /login
or /callback
directly#
The endpoints /auth/v2/login
and /auth/v2/callback
are internal
coordination points for the authentication process:
/login
initiates the code flow by redirecting to the OpenID Connect provider./callback
is the endpoint where the OpenID provider sends the authorization code.
These endpoints are not designed for direct use by end users or typical API consumers. Calling them directly will likely lead to errors or unexpected behaviour.
Instead, you should authenticate using one of the supported client tools:
The Python client: via :py:func``freva_client.authenticate``
The CLI tool: via
freva-client auth
The web portal: to manually log in and download a token file
These interfaces abstract away the complexity and ensure the flow is handled securely and correctly.
For Service Providers (SPs)#
If you are building a custom SP (e.g. a web service or interactive tool that needs to act on behalf of a user), then it is appropriate to interact with the code flow endpoints directly — but only with care.
Follow these steps:
Redirect the user to Freva’s
/login
endpoint:GET /api/freva-nextgen/auth/v2/login?redirect_uri=https://your-sp.com/callback HTTP/1.1 host: www.freva.dkrz.de
The
redirect_uri
must be a publicly accessible endpoint on your service that handles the code exchange.
User authenticates via the upstream Identity Provider (e.g., Keycloak).
The Identity Provider redirects back to your service’s
/callback
endpoint with a code and state query parameter.Your SP must then POST the code to Freva’s token exchange endpoint:
POST /api/freva-nextgen/auth/v2/token HTTP/1.1 host: www.freva.dkrz.de Content-Type: application/x-www-form-urlencoded { code=XXX&redirect_uri=https://your-sp.com/callback }
This will return a JSON with access token, refresh token, and expiry info.
Use the access token to authenticate future API requests.
Optionally refresh the token before expiry using:
POST /api/freva-nextgen/auth/v2/token HTTP/1.1 host: www.freva.dkrz.de Content-Type: application/x-www-form-urlencoded { grant_type=refresh_token&refresh_token=YYY }
Note
You do not need to manage client secrets for browser-based SPs.
The
redirect_uri
must match one of the values registered with the OIDC provider.If you are building a backend-for-frontend (BFF) architecture, handle the token exchange server-side to protect credentials.
This is the recommended approach for implementing a standards-compliant OAuth2 Authorization Code Flow as a Service Provider.