Remote Authenticator
Remote Authenticator is a pluggable architecture for lakeFS which allows you to use existing organizational identity policies and infrastructure with the authentication mechanism of lakeFS. The Remote Authenticator’s job is to abstract away the complexities of existing infrastructure and implement a standard interface, which lakeFS can use to resolve user identity and manage access to lakeFS. This loose coupling allows you to implement federated identity without providing lakeFS with direct access to your identity infrastructure.
Architecture
Here’s the authentication flow that lakeFS uses when configured with a remote authenticator:
sequenceDiagram
participant A as lakeFS Client
participant B as lakeFS Server
participant C as Remote Authenticator
participant D as IdP
A->>B: Submit login form
B->>C: POST user credentials
C->>D: IdP request
D->>C: IdP response
C->>B: Auth response
B->>A: auth JWT
The Interface
To configure lakeFS to work with a Remote Authenticator add the following YAML to your lakeFS configuration:
auth:
remote_authenticator:
enabled: true
endpoint: <url-to-remote-authenticator-endpoint>
default_user_group: "Developers"
ui_config:
logout_url: /logout
login_cookie_names:
- internal_auth_session
auth.remote_authenticator.enabled
- set lakeFS to use the remote authenticatorauth.remote_authenticator.endpoint
- an endpoint where the remote authenticator is able to receive a POST request from lakeFSauth.remote_authenticator.default_user_group
- the group assigned by default to new usersauth.ui_config.logout_url
- the URL to redirect the browser when clicking the logout link in the user menuauth.ui_config.login_cookie_names
- the name of the cookie(s) lakeFS will set following a successful authentication. The value is the authenticated user’s JWT
A Remote Authenticator implementation should expose a single endpoint, which expects the following JSON request:
{
"username": "testy.mctestface@example.com",
"password": "Password1"
}
and returns a JSON response like this:
{
"external_user_identifier": "TestyMcTestface"
}
Example Request & Responses
Request
POST https://remote-authenticator.example.com/auth
Content-Type: application/json
{
"username": "testy.mctestface@example.com",
"password": "Password1"
}
Successful Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"external_user_identifier": "TestyMcTestface"
}
Unauthorized Response
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"external_user_identifier": ""
}
If the Remote Authenticator returns any HTTP status in the 2xx range, lakeFS considers this a successful authentication. Any HTTP status < 200 or > 300 is considered a failed authentication. If the Remote Authenticator returns a non-empty value for the external_user_identifier
property along with a success HTTP status, lakeFS will show this identifier instead of an internal lakeFS user identifier in the UI.
Sample Implementation
Here is a sample Remote Authenticator implemented using node and express and written in TypeScript. This example implementation doesn’t integrate with any real IdP but illustrates the expected request/response patterns that you need to implement.
import dotenv from "dotenv";
import express, { Express, Request, Response } from "express";
import { StatusCodes } from "http-status-codes";
type AuthRequestBody = {
username: string;
password: string;
};
type AuthResponseBody = {
external_user_identifier: string;
};
const DEFAULT_PORT = 80;
dotenv.config();
const port = process.env.PORT || DEFAULT_PORT;
const app: Express = express();
app.post(
"/auth",
(req: Request<AuthResponseBody, {}, AuthRequestBody>, res: Response) => {
const { username, password } = req.body;
if (!username?.length || !password?.length) {
return res.status(StatusCodes.BAD_REQUEST).json({
external_user_identifier: "",
});
}
// 👇🏻 This is where you would implement your own authentication logic
if (
username === "testy.mctestface@example.com" &&
password === "Password1"
) {
return res.status(StatusCodes.OK).json({
external_user_identifier: "TestyMcTestface",
});
} else {
return res.status(StatusCodes.UNAUTHORIZED).json({
external_user_identifier: "",
});
}
}
);
app.listen(port, () => {
console.log(`Remote Authenticator listening on port ${port}`);
});
To run this service on the sub-domain idp.example.com
, use a lakeFS configuration that looks like this:
auth:
remote_authenticator:
enabled: true
endpoint: https://idp.example.com/auth
default_user_group: "Developers"
ui_config:
logout_url: /logout
login_cookie_names:
- internal_auth_session