.github/media | ||
cmd/werther | ||
internal | ||
.codecov.yml | ||
.golangci.yml | ||
Dockerfile | ||
go.mod | ||
go.sum | ||
LICENSE | ||
README.md |
Werther 1
Werther is an Identity Provider for ORY Hydra over LDAP. It implements Login And Consent Flow and provides basic UI.
Features
- Support Active Directory;
- Mapping LDAP attributes to OpenID Connect claims;
- Mapping LDAP groups to user roles;
- OAuth 2.0 scopes;
- Caching users roles;
- UI customization.
Limitations
- Werther grants all requested permissions to a client without displaying the consent page;
- Werther confirms a logout request without displaying the logout confirmation page.
Requirements
ORY Hydra v1.0.0-rc.12 or higher.
Table of Contents
Installing
From Docker
docker pull icoreru/werter
From sources
go install ./...
Usage
-
Create a network:
docker network create hydra-net
-
Run ORY Hydra:
docker run --network hydra-net -d --restart always --name hydra \ -p 4444:4444 \ -p 4445:4445 \ -e URLS_SELF_ISSUER=http://localhost:4444 \ -e URLS_SELF_PUBLIC=http://localhost:4444 \ -e URLS_LOGIN=http://localhost:8080/auth/login \ -e URLS_CONSENT=http://localhost:8080/auth/consent \ -e URLS_LOGOUT=http://localhost:8080/auth/logout \ -e WEBFINGER_OIDC_DISCOVERY_SUPPORTED_SCOPES=profile,email,phone \ -e WEBFINGER_OIDC_DISCOVERY_SUPPORTED_CLAIMS=name,family_name,given_name,nickname,email,phone_number \ -e DSN=memory \ oryd/hydra:v1.0.0-rc.12 serve all
Look for details in ORY Hydra Configuration and ORY Hydra Documentation.
-
Run Werther:
docker run --network hydra-net -d --restart always --name werther \ -p 8080:8080 \ -e WERTHER_IDENTP_HYDRA_URL=http://hydra:4445 \ -e WERTHER_LDAP_ENDPOINTS=icdc0.example.local:389,icdc1.example.local:389 \ -e WERTHER_LDAP_BINDDN=<BINDDN> \ -e WERTHER_LDAP_BINDPW=<BINDDN_PASSWORD> \ -e WERTHER_LDAP_BASEDN="DC=example,DC=local" \ -e WERTHER_LDAP_ROLE_BASEDN="OU=AppRoles,OU=Domain Groups,DC=example,DC=local" \ icoreru/werther
Configuration
The application is configured via environment variables.
Names of the environment variables starts with prefix WERTHER_
.
See a list of the environment variables using the command:
werther -h
User roles
In LDAP user's roles are groups in which a user is a member.
The environment variable WERTHER_LDAP_ROLE_DN
is a DN for searching roles.
For example, create an OU that repserents an application, and then in the created OU create groups that represent application's roles:
DC=local
|-- OU=Domain Groups
|-- OU=AppRoles
|-- OU=App1
|-- CN=app1_role1 (objectClass="group", description="role1")
|-- CN=app1_role2 (objectClass="group", description="role2")
Run Werther with the environment variable WERTHER_LDAP_ROLE_DN
that equals to OU=AppRoles,OU=Domain Groups,DC=local
.
In the above example Werther returns user's roles as a value
of the user role's claim https://github.com/i-core/werther/claims/roles
.
{
"https://github.com/i-core/werther/claims/roles": {
"App1": ["role1", "role2"],
}
}
To customize the roles claim's name you should set a value of the environment variable WERTHER_LDAP_ROLE_CLAIM
.
For more details about claims naming see OpenID Connect Core 1.0.
NB There are cases when we need to create several roles with the same name in LDAP. For example, when we want to configure multiple applications or several environments for the same application.
DC=local
|-- OU=Domain Groups
|-- OU=AppRoles
|-- OU=Test
|-- OU=App1
|-- CN=test_app1_role1 (objectClass="group", description="role1")
|-- CN=test_app1_role2 (objectClass="group", description="role2")
|-- OU=App2
|-- CN=test_app2_role1 (objectClass="group",description-"role1")
|-- CN=test_app2_role2 (objectClass="group",description-"role2")
|-- OU=Dev
|-- OU=App1
|-- CN=dev_app1_role1 (objectClass="group", description="role1")
|-- CN=dev_app1_role3 (objectClass="group", description="role3")
|-- OU=App2
|-- CN=dev_app2_role1 (objectClass="group",description-"role1")
|-- CN=dev_app2_role4 (objectClass="group",description-"role4")
Active Directory requires unique CNs in a domain. But in Active Directory
creating groups with the same CN in different OUs is difficult.
Because of it, Werther uses a LDAP attribute as a role's name instead of CN.
A name of a LDAP attribute is specified using the environment variable WERTHER_LDAP_ROLE_ATTR
,
and has the default value description
.
In the above example, Werther returns a response that contains the next roles:
- when the environment variable
WERTHER_LDAP_ROLE_DN
equals toOU=Test,OU=AppRoles,OU=Domain Groups,DC=local
:{ "https://github.com/i-core/werther/claims/roles": { "App1": ["role1", "role2"], "App2": ["role1", "role2"] } }
- when the environment variable
WERTHER_LDAP_ROLE_DN
equals toOU=Dev,OU=AppRoles,OU=Domain Groups,DC=local
:{ "https://github.com/i-core/werther/claims/roles": { "App1": ["role1", "role3"], "App2": ["role1", "role4"] } }
UI customization
Werther uses the Go templates to render UI pages.
To customize the UI you should create a directory that contains UI pages' templates.
After that you should set the directory path to the environment variable WERTHER_WEB_DIR
:
docker run --network hydra-net -d --restart always --name werther \
-p 8080:8080 \
-v /opt/werther/web:/path/to/custom-login-page/dir \
-e WERTHER_IDENTP_HYDRA_URL=http://hydra:4445 \
-e WERTHER_LDAP_ENDPOINTS=icdc0.example.local:389,icdc1.example.local:389 \
-e WERTHER_LDAP_BINDDN=<BINDDN> \
-e WERTHER_LDAP_BINDPW=<BINDDN_PASSWORD> \
-e WERTHER_LDAP_BASEDN="DC=example,DC=local" \
-e WERTHER_LDAP_ROLE_BASEDN="OU=AppRoles,OU=Domain Groups,DC=example,DC=local" \
-e WERTHER_WEB_DIR=/opt/werther/web
icoreru/werther
Custom login page
A login page's template should contains blocks title
, style
, script
, content
.
Each block has access to data that is an object with the next properties:
CSRFToken
(string) - a CSRF token;Challenge
(string) - a login challenge ID;LoginURL
(string) - an endpoint that finishes the login process;IsInvalidCredentials
(bool) - specifies that a user types an invalid username or password;IsInternalError
(bool) specifies that an internal server error happens when finishing the login process.
When a login page's template contains static resources (like styles, scripts, and images)
they must be placed in a subdirectory called static
.
For a full example of a login page's template see source code.
Resources
- Introduction to ORY Hydra, OAuth 2.0, and OpenID Connect;
- ORY Hydra: Integrating with (existing) User Management;
- Official User Login & Consent Example;
- OpenID Connect Core 1.0;
- OpenID Connect Session Management 1.0;
- OpenID Connect Front-Channel Logout 1.0;
- OpenID Connect Back-Channel Logout 1.0.
Footnotes
- Werther is named after robot Werther from Guest from the Future.
Contributing
Thanks for your interest in contributing to this project. Get started with our Contributing Guide.
License
The code in this project is licensed under MIT license.