Skip to content

Conversation

@Ceirced
Copy link

@Ceirced Ceirced commented Aug 22, 2025

Use env variable to enable ldap integration.

Working config with forumsys ldap.

Add env varibale to disable local auth.

@XeR
Copy link
Contributor

XeR commented Sep 2, 2025

Hi!

Thanks for the PR. (and the 2 others) This looks like a lot of work!
I'm excited about this one. I've been meaning to do something like this for a while and migrate our team's infra to LDAP.
This would let us have a single account for CTFNote, Hedgedoc and potentially other services.

Related to issue #171

Adapted the reolution of the ldap groups to not only work with the example ldap from forumsys but also with a freeIpa setup.
@benzo-benzin
Copy link

Hi XeR,

currently reviewing the patches from Ceirced and working on improving error handling, bug fixes, and better integration of mattermost channels as well as gitlab repos.

Cheers,
defragmented.brains

Copy link
Contributor

@Minei3oat Minei3oat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably try to align your function/variable/... names better with the existing code base.

PS: I'm no maintainer, so feel free to ignore my feedback

return "user_member";
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing check for friend role (#94)

// Explicitly specify algorithm to prevent algorithm confusion attacks
const signedJwt = jwt.sign(jwtPayload, jwtSecret, {
algorithm: "HS256",
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If SESSION_SECRET is too short, CTFNote will generate a new secret on every start, but your jwtSecret will be the too short value. As a result, the JWT generated here will fail validation with invalid signature.
If SESSION_SECRET is not set, jwtSecret is empty, resulting in an error during signing:
Error: secretOrPrivateKey must have a value


try {
// Additional check to ensure the user is recognized as logged in
const loginCheck = await isLogged();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This returns false since there is no data in cache.

jwt
}
}
`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mutation should be defined in /front/src/graphql/Auth.graphql

LDAP_GROUP_ATTRIBUTE=ou
LDAP_ADMIN_GROUPS=mathematicians
LDAP_MANAGER_GROUPS=scientists
LDAP_USER_GROUPS=chemists
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should either use singular or support specifying multiple groups

# Role Mapping
LDAP_DEFAULT_ROLE=user_guest
LDAP_MATHEMATICIANS_ROLE=user_member
LDAP_SCIENTISTS_ROLE=user_member
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file seems to be for an earlier version of this PR and seems wrong for the current version

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is likely relevant for docker, so you should probably keep it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is likely relevant for local development/build on linux, so you should probably keep it

query getAuthSettings {
localAuthEnabled
ldapAuthEnabled
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This query should probably be moved into /front/src/graphql/Settings.graphql

}
`;

export function useLdapLogin() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After moving the graphql to the graphql file, you can just use similar code as useLogin.

-- Add LDAP user authentication function
-- This function will be called from the LDAP plugin to handle user creation/update

CREATE OR REPLACE FUNCTION ctfnote.login_ldap(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must be a private function, because if it is public, I can use it to request a JWT for arbitrary (non-existing) users with arbitrary roles:

[{"operationName":"LoginLdap","variables":{"username":"test","userRole":"USER_ADMIN"},"query":"mutation LoginLdap($username: String!, $userRole: Role!) {\n  loginLdap(input: {username: $username, userRole: $userRole}) {\n    jwt\n    __typename\n  }\n}"}]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants