Auth system integrations (Enterprise)
Memgraph supports authentication and authorization using external auth modules. It includes built-in support for basic (username and password) authentication via LDAP, as well as single sign-on over the SAML and OIDC protocols.
When a user is connecting, Memgraph will forward the user’s supplied credentials (username and password, or scheme and auth response) to the external auth module and retrieve its verdict. Based on this verdict, Memgraph will either allow the user to connect or, in case of failure, close the connection.
As this is an Enterprise feature, once the Memgraph Enterprise license expires, newly created users will be granted all privileges. The existing users' privileges will still apply but you won't be able to manage them.
Configuration
Roles
User roles must be defined in Memgraph before using auth modules because these modules return the role associated with the user.
Flags
Use the following configuration flags to configure the external auth module authentication and authorization mechanisms used by Memgraph.
Flag | Description |
---|---|
--auth-module-mappings | Associates auth schemes to external modules. A mapping is structured as follows: <scheme>:<absolute path to module> and individual entries are separated with ; . If the mapping contains whitespace, enclose the flag value with quotation marks. |
--auth-module-executable | [DEPRECATED] Path to the executable that should be used for user authentication/authorization. Replaced by --auth-module-mappings=basic from Memgraph 2.18. |
--auth-module-timeout-ms | Specifies the maximum time that Memgraph will wait for a response from the external auth module. |
--auth-password-permit-null | Can be set to false to disable null passwords. |
--auth-password-strength-regex | The regular expression that should be used to match the entire entered password to ensure its strength. |
Auth schemes that have built-in Memgraph support have default module paths. To
enable them, you only need to list the auth schemes themselves, e.g.
--auth-module-mappings=basic;saml-entra-id;oidc-okta
.
The schemes with built-in support are:
basic
(username + password authentication with external module)saml-entra-id
saml-okta
oidc-entra-id
oidc-okta
Environment variables
The built-in auth modules (used with the saml-entra-id
, saml-okta
,
oidc-entra-id
, and oidc-okta
auth schemes) are further configured using
environment variables. See the individual SSO module sections for more detail.
Auth module architecture
Communication
Memgraph uses inter-process pipes to communicate with the module. The module
will receive auth requests on file descriptor 1000
and has to return auth
responses to file descriptor 1001
. The standard streams (stdin
and stdout
)
aren't used because external libraries often tend to write something to stdout
which is difficult to disable. By using separate file descriptors, stdout
is
left intact and can be used freely for debugging purposes (along with stderr
).
The protocol used between Memgraph and the module is as follows:
- Each auth request is sent as a JSON encoded object in a single line that is
terminated by a
\n
. - Each auth response must be sent as a JSON encoded object in a single line
that is terminated by a
\n
. - Auth requests are objects that contain the following fields:
basic
auth scheme:username
- the user's usernamepassword
- the user's password- other auth schemes:
scheme
- the string representing the auth method, e.g.oidc-entra-id
response
- the authentication response (e.g. SAML response or JWT)
- Auth responses must be objects that contain the following fields:
authenticated
- abool
indicating whether the user is allowed to log in to the databaserole
- astring
indicating which role the user should have (must be supplied)errors
(optional) - ifauthenticated
is false, Memgraph will put up a warning with the error message returned by the module
If the external auth module crashes during the processing of an auth request,
Memgraph won't allow the user to log in to the database and will automatically
restart the auth module for the next auth request. All crash logs will be seen
in Memgraph's output (typically in systemd
logs using journalctl
).
Module example
This very simple example auth module is written in Python, but any programming language can be used.
#!/usr/bin/python3
import json
import io
def authenticate(username, password):
return {"authenticated": True, "role": "moderator"}
if __name__ == "__main__":
input_stream = io.FileIO(1000, mode="r")
output_stream = io.FileIO(1001, mode="w")
while True:
params = json.loads(input_stream.readline().decode("ascii"))
ret = authenticate(**params)
output_stream.write((json.dumps(ret) + "\n").encode("ascii"))
In the example you can see how the communication protocol works and you can see
the function that is used for authentication (and authorization). When writing
your own modules, you have to reimplement the authenticate
function according
to your needs.
Because the authentication (and authorization) function has a simple signature, it is easy (and recommended) to write unit (or integration) tests in separate files. For example:
#!/usr/bin/python3
import module
assert module.authenticate("sponge", "bob") == {"authenticated": True, "role": "analyst"}
assert module.authenticate("CHUCK", "NORRIS") == {"authenticated": True, "role": "admin"}
Single sign-on
Single sign-on (SSO) lets you use an external ID to log in to Memgraph from Lab.
The built-in SSO modules let you customize which data from the identity service supplies the username and password. Username configuration is service- and protocol-specific, whereas role configuration works universally via remapping.
The MEMGRAPH_SSO_{provider}_{protocol}_ROLE_MAPPING
flags define how the
identity service roles correspond to Memgraph’s.
The role mapping is defined as a string where individual mappings are separated
by a semicolon ;
. Each mapping is structured as follows:
{identity service role}:{Memgraph role}
.
For example, the entra.admin:memadmin; entra.user:memuser
mapping defines
that the identity service roles entra.admin
and entra.user
respectively map
to Memgraph’s memadmin
and memuser
roles.
For correct operation, the Memgraph roles defined in the mapping need to be created in the Memgraph DB beforehand. Additionally, you have to grant label-based permissions to the roles used in SSO.
SAML
Memgraph has built-in support for single sign-on (SSO) over the SAML protocol with the Microsoft Entra ID and Okta identity providers.
Configuration
To enable SAML SSO using the built-in auth modules, set the
--auth-module-mappings
with the saml-entra-id
or saml-okta
schemes, e.g.
--auth-module-mappings=saml-entra-id;saml-okta
(or just one of them).
The following environment variables are used to configure the built-in SAML module:
Entra ID
MEMGRAPH_SSO_ENTRA_ID_SAML_CALLBACK_URL
: the same asAUTH_SAML_ENTRA_ID_CALLBACK_URL
for Memgraph LabMEMGRAPH_SSO_ENTRA_ID_SAML_ASSERTION_AUDIENCE
: the application audience (opens in a new tab); for single-tenant apps, equal tospn:{tenant id}
MEMGRAPH_SSO_ENTRA_ID_SAML_IDP_CERT
: the path to the application’s SAML certificate (opens in a new tab)MEMGRAPH_SSO_ENTRA_ID_SAML_IDP_ID
: equal tohttps://sts.windows.net/{tenant id}/
MEMGRAPH_SSO_ENTRA_ID_SAML_ASSERTIONS_ENCRYPTED
: set to true if Entra ID is configured to encrypt assertions in the SAML responseMEMGRAPH_SSO_ENTRA_ID_SAML_SP_PRIVATE_KEY
: if using a private key to decrypt assertions, set this flag’s value to the path to the keyMEMGRAPH_SSO_ENTRA_ID_SAML_WANT_ATTRIBUTE_STATEMENT
: set to true if the Entra ID SAML response is required to contain attributesMEMGRAPH_SSO_ENTRA_ID_SAML_USE_NAME_ID
: set to true in order to supply the username from the SAML NameID attributeMEMGRAPH_SSO_ENTRA_ID_NAME_ID_ENCRYPTED
: set to true if Entra ID is configured to encrypt the NameID elementMEMGRAPH_SSO_ENTRA_ID_SAML_USERNAME_ATTRIBUTE
: if not using NameID, set the name of the SAML response attribute that contains the usernameMEMGRAPH_SSO_ENTRA_ID_SAML_ROLE_MAPPING
: the role mapping
Okta
MEMGRAPH_SSO_OKTA_SAML_CALLBACK_URL
: the same asAUTH_SAML_OKTA_CALLBACK_URL
for Memgraph LabMEMGRAPH_SSO_OKTA_SAML_ASSERTION_AUDIENCE
: the application audience (opens in a new tab)MEMGRAPH_SSO_OKTA_ID_SAML_IDP_CERT
: the path to the application’s SAML certificate (opens in a new tab)MEMGRAPH_SSO_OKTA_SAML_IDP_ID
: the Okta issuer URL (opens in a new tab)MEMGRAPH_SSO_OKTA_SAML_ASSERTIONS_ENCRYPTED
: set to true if Okta is configured to encrypt assertions in the SAML responseMEMGRAPH_SSO_OKTA_SAML_SP_PRIVATE_KEY
: if using a private key to decrypt assertions, set this flag’s value to the path to the keyMEMGRAPH_SSO_OKTA_SAML_WANT_ATTRIBUTE_STATEMENT
: set to true if the Okta SAML response is required to contain attributesMEMGRAPH_SSO_OKTA_SAML_USE_NAME_ID
: set to true in order to supply the username from the SAML NameID attributeMEMGRAPH_SSO_OKTA_NAME_ID_ENCRYPTED
: set to true if Okta is configured to encrypt the NameID elementMEMGRAPH_SSO_OKTA_SAML_USERNAME_ATTRIBUTE
: if not using NameID, set the name of the SAML response attribute that contains the usernameMEMGRAPH_SSO_OKTA_SAML_ROLE_ATTRIBUTE
: set the name of the SAML response attribute that contains the user roleMEMGRAPH_SSO_OKTA_SAML_ROLE_MAPPING
: the role mapping
OpenID Connect (OIDC)
Memgraph also supports authentication and authorization using OIDC (OIDC + OAuth 2.0) protocol with a built-in auth module that is packaged with Memgraph Enterprise.
The module currently supports the following SSO providers:
- Microsoft Entra ID
- Okta using a custom authorization server
To use the built-in auth module run Memgraph with the --auth-module-mappings
flag with the name of each provider and protocol you want to use separated with a semicolon (;).
For example, to use OIDC with both Entra ID and Okta run Memgraph with --auth-module-mappings=oidc-okta;oidc-entra-id
.
For SSO provider setup see this.
Module requirements
The module is written in Python 3 and requires the following libraries:
PyJWT
- used to validate tokens.requests
- used to retrieve public keys for validating tokens.cryptography
- used to parse tokens.
The required packages are already installed in the docker image. If you are using a native build you to install the packages manually on your machine.
The list of all required packages is located at src/auth/reference_modules/requirements.txt
. You can install them by running pip3 install -r /path/to/requirements.txt
.
If you are running a native build make sure that you don't have the Python JWT
library installed (you can check that with pip freeze
) as PyJWT
and JWT
have some conflicts.
Module configuration
The module is located at /usr/lib/memgraph/auth_module/oidc.py
.
The module has no configuration file. You have to run Memgraph with some environmental variables.
To use multiple SSO providers you have to set the environmental variables associated with that provider.
MS Entra ID
For using OIDC with Microsoft Entra ID you have to set the following environmental variables:
MEMGRAPH_SSO_ENTRA_ID_OIDC_TENANT_ID=
MEMGRAPH_SSO_ENTRA_ID_OIDC_CLIENT_ID=
MEMGRAPH_SSO_ENTRA_ID_OIDC_ROLE_MAPPING=
MEMGRAPH_SSO_ENTRA_ID_OIDC_USERNAME=
You can find the tenant and client ID in the app overview in Azure. For a more detailed explanation see this.
Role mapping is described here.
The username variable tells the OIDC module what to use as the username. It has the format token-type:field
.
Token type can be id
or access
depending on whether you want to use a field from the access or the ID token for the username. See the following to learn more about access (opens in a new tab) and id (opens in a new tab) tokens.
By default, it is set to id:sub
as per the OIDC protocol it is recommended to use the sub
field from the id token as it is non-mutable and globally unique for each application.
For MS Entra ID one commonly used field is access:preferred_username
which is usually the email of the user. For a list of all default claims look at this (opens in a new tab) and this (opens in a new tab).
You can also configure custom claims.
Okta
For using OIDC with Okta you have to set the following environmental variables:
MEMGRAPH_SSO_OKTA_OIDC_ISSUER=
MEMGRAPH_SSO_OKTA_OIDC_CLIENT_ID=
MEMGRAPH_SSO_OKTA_OIDC_AUTHORIZATION_SERVER=api://default
MEMGRAPH_SSO_OKTA_OIDC_ROLE_MAPPING=
MEMGRAPH_SSO_OKTA_OIDC_USERNAME=
Role mapping is described here.
Issuer is https://{your-okta-domain}.okta.com/oauth2/default/
. You can find the client ID on the Admin panel -> Applications -> General. You can find the authorization server on the Admin panel -> Security -> API -> Authorization Servers -> Audience. By default, it is set to api://default
.
Username
The username variable tells the OIDC module what to use as the username. It has the format token-type:field
.
Token type can be id
or access
depending on whether you want to use a field from the access or the ID token for the username. See the following to learn more about access (opens in a new tab) and id (opens in a new tab) tokens.
By default, it is set to id:sub
as per the OIDC protocol it is recommended to use the sub
field from the id token as it is non-mutable and globally unique for each application.
For Okta one commonly used field is access:sub
which is usually the email of the user. You can also configure custom claims (opens in a new tab).
Database configuration
OIDC is by default enabled using the Memgraph oidc.py
module. To use a custom auth module use the --auth-module-mappings
flag like the following:
--auth-module-mappings=oidc-entra-id:/path/to/oidc-entra-module;oidc-okta:/path/to/oidc-okta-module
depending on the SSO provider you want to use.
Basic (username + password) auth
When Memgraph is set up to use the external auth module for basic authentication
(--auth-module-mappings=basic
), its internal users are automatically disabled.
Users are authenticated only using the module and existing local users are
ignored.
LDAP
Memgraph also supports authentication and authorization using LDAP with a built-in auth module that is packaged with Memgraph Enterprise.
The module supports the authentication and authorization (LDAP bind and search requests) operation mode.
Mode of operation
When using LDAP authentication the module builds the DN used for authentication using the user specified username and the following formula:
DN = prefix + username + suffix
In most common situations the prefix
will be cn=
and the suffix
will be
,dc=example,dc=com
. With an example username alice
that would yield a DN
equal to cn=alice,dc=example,dc=com
which will then be used for the LDAP bind
operation with the user specified password.
After the user is authenticated, the module searches through the role mapping
root DN object that contains role mappings. A role mapping object that has the
current bound user as its member
attribute is used as the user's role.
The role that is mapped to the user is the CN
attribute of the role mapping
object. The attribute that contains the user DN in the mapping object, as well
as the attribute that contains the role name, can be changed in the module
configuration file to accommodate your LDAP schema.
When searching for a role in directories that have thousands of roles, the search process could take some time, causing long login times.
Module requirements
The module is written in Python 3 and it must be installed on the server. The
Python version should be at least 3.5
. Also, you must have the following
Python 3 libraries installed:
ldap3
- used to communicate with the LDAP server.PyYAML
- used to parse the configuration file.
Module configuration
The module configuration file is located at
/etc/memgraph/auth_module/ldap.yaml
. An initial example configuration file
that has all settings documented and explained is located at
/etc/memgraph/auth_module/ldap.example.yaml
. For quick setup, you can copy the example
configuration file into the module configuration file.
Database configuration
In order to enable the use of the LDAP authentication and authorization module
you have to set the following flag: --auth-module-mappings=basic
.
Other flags that change the behavior of the database to module integration can be specified according to your needs.
Example
Organizations typically use an LDAP server to hold and manage the permissions. Because LDAP servers are already set-up in most large organizations, it is convenient for the organization to allow all staff members to have access to the database using the already available centralized user management system.
For this guide let's assume that we have an LDAP server that is serving the following data:
# Users root entry
dn: ou=people,dc=memgraph,dc=com
objectclass: organizationalUnit
objectclass: top
ou: people
# User dba
dn: cn=dba,ou=people,dc=memgraph,dc=com
cn: dba
objectclass: person
objectclass: top
sn: user
userpassword: dba
# User alice
dn: cn=alice,ou=people,dc=memgraph,dc=com
cn: alice
objectclass: person
objectclass: top
sn: user
userpassword: alice
# User carol
dn: cn=carol,ou=people,dc=memgraph,dc=com
cn: carol
objectclass: person
objectclass: top
sn: user
userpassword: carol
# User dave
dn: cn=dave,ou=people,dc=memgraph,dc=com
cn: dave
objectclass: person
objectclass: top
sn: user
userpassword: dave
# Roles root entry
dn: ou=roles,dc=memgraph,dc=com
objectclass: organizationalUnit
objectclass: top
ou: roles
# Role superuser
dn: cn=superuser,ou=roles,dc=memgraph,dc=com
cn: superuser
member: cn=dba,ou=people,dc=memgraph,dc=com
objectclass: groupOfNames
objectclass: top
# Role moderator
dn: cn=moderator,ou=roles,dc=memgraph,dc=com
cn: moderator
member: cn=alice,ou=people,dc=memgraph,dc=com
objectclass: groupOfNames
objectclass: top
# Role admin
dn: cn=admin,ou=roles,dc=memgraph,dc=com
cn: admin
member: cn=carol,ou=people,dc=memgraph,dc=com
member: cn=dave,ou=people,dc=memgraph,dc=com
objectclass: groupOfNames
objectclass: top
To summarize, the dataset contains the following data:
ou=people,dc=memgraph,dc=com
- entry that holds all users.cn=dba,ou=people,dc=memgraph,dc=com
- userdba
that will be used as the database administrator.cn=alice,ou=people,dc=memgraph,dc=com
- regular useralice
.cn=carol,ou=people,dc=memgraph,dc=com
- regular usercarol
.cn=dave,ou=people,dc=memgraph,dc=com
- regular userdave
.
ou=roles,dc=memgraph,dc=com
- entry that holds all roles.cn=moderator,ou=roles,dc=memgraph,dc=com
- rolemoderator
that hasalice
as its member.cn=admin,ou=roles,dc=memgraph,dc=com
- roleadmin
that hascarol
anddave
as its members.
Authentication
Run Memgraph
Firs, prepare Memgraph for the integration with LDAP. Run a Memgraph instance without any users in its local authentication storage. For more details on how the native authentication storage works in Memgraph check user privileges.
Create an administrator
When using the module, all users are handled by the auth module and no user information is stored locally in Memgraph. In order to allow user login, the corresponding roles need to be defined locally.
CREATE ROLE superuser;
GRANT ALL PRIVILEGES TO superuser;
Once the role has been created and all privileges granted, it's safe to disconnect from the database and proceed with the LDAP integration.
Enable LDAP integration
To enable LDAP integration specify the following flag:
--auth-module-mappings=basic
Also, add the following LDAP module configuration to
/etc/memgraph/auth_module/ldap.yaml
:
server:
host: "<LDAP_SERVER_HOSTNAME>"
port: <LDAP_SERVER_PORT>
encryption: "disabled"
cert_file: ""
key_file: ""
ca_file: ""
validate_cert: false
users:
prefix: "cn="
suffix: ",ou=people,dc=memgraph,dc=com"
roles:
root_dn: ""
root_objectclass: ""
user_attribute: ""
role_attribute: ""
Adjust the security settings according to your LDAP server security settings.
Once all the configuration options are set, restart the Memgraph database instance.
Check the integration
Verify that you can log into the database using the username dba
and password
dba
. It will confirm that the LDAP authentication is successfully enabled.
Log in other users
User alice
should be able to log in with password alice
.
The administrator dba
should modify Alice's role's privileges to include the
MATCH
privilege using the following query:
GRANT MATCH TO moderator;
Once Alice logs in the second time, she should be able to execute the following query:
MATCH (n) RETURN n;
If the dba
runs the SHOW USERS;
query, it won't return any users, since all
users are managed by the auth module.
Users Bob, Carol and Dave will also be able to log in to the database using their LDAP password.
Authorization
Enable role mapping
To enable role mapping for the described LDAP schema, modify the LDAP auth
module configuration file, specifically the section roles
, by adding the
following content:
roles:
root_dn: "ou=roles,dc=memgraph,dc=com"
root_objectclass: "groupOfNames"
user_attribute: "member"
role_attribute: "cn"
This configuration tells the LDAP module that all role mapping entries are
children of the ou=roles,dc=memgraph,dc=com
entry, that the children have
user DNs specified in their member
attribute and that the cn
attribute
should be used to determine the role name.
When a user logs in to the database, the LDAP auth module will go through all role mapping entries and will try to find out which role mapping entry has the user as its member.
So now when Alice logs in, the LDAP auth module will go through the following
entries: cn=admin,ou=roles,dc=memgraph,dc=com
and
cn=moderator,ou=roles,dc=memgraph,dc=com
. Because Alice is a member of the
moderator
role mapping, the LDAP auth module will assign role moderator to
Alice.
Adjust permissions
Permissions for users and roles are still managed through Memgraph, they can't be managed through the LDAP server.
The database administrator (user dba
) now has to explicitly create the role
the users have so they will be able to log into the database:
CREATE ROLE moderator;
In this scenario Alice and Bob will be able to log in. Alice will be allowed to log in because her role (moderator) already exists. Carol and Dave won't be allowed to log in because their role (administrator) doesn't exist.