Skip to content

Commit

Permalink
Add script authenticators (#1)
Browse files Browse the repository at this point in the history
* Add user-enabled-authenticator

* Use OpenJDK 21 and bump version

* Add CSM Authenticator and Authorization Authenticator

* Include version in jar name

* Make name shorter

* Replace getAttribute with getFirstAttribute
  • Loading branch information
treydock authored Nov 18, 2024
1 parent 3316bf3 commit fbe70b1
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 8 deletions.
18 changes: 17 additions & 1 deletion META-INF/keycloak-scripts.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
{
"authenticators": [],
"authenticators": [
{
"name": "User Enabled Authenticator",
"fileName": "user-enabled-authenticator.js",
"description": "Allow only enabled users"
},
{
"name": "CSM Authenticator",
"fileName": "csm-authenticator.js",
"description": "CSM EmployeeStatus Authenticator"
},
{
"name": "Authorization Authenticator",
"fileName": "authz-authenticator.js",
"description": "Authorization Authenticator"
}
],
"policies": [],
"mappers": [],
"saml-mappers": [
Expand Down
34 changes: 34 additions & 0 deletions authz-authenticator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

function authenticate(context) {

if (!authenticationSession.getClient()) {
context.failure(AuthenticationFlowError.CLIENT_NOT_FOUND);
return;
}
var client = authenticationSession.getClient().getClientId();
LOG.info(script.name + " evalute authorization for user=" + user.username + " client=" + client);
/*
Use employeeStatus verification for service-now which allows some disabled
states to still authenticate.
Also allow class-dev for testing purposes.
*/
if (client && (client.contains("service-now") || client.contains("class-dev"))) {
var allowed = /(REQAPPROVAL|ACTIVE|WEBONLY|RESTRICTED)/;
var employeeStatus = user.getFirstAttribute("employeeStatus");
if (employeeStatus && !allowed.test(employeeStatus)) {
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}
} else {
/*
All other clients will authorize if the user account is not disabled or locked
*/
if (user.getFirstAttribute("nsAccountLock") == "TRUE" || user.getFirstAttribute("loginDisabled") == "TRUE") {
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}
}

context.success();
}
7 changes: 4 additions & 3 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
FROM rockylinux:8
RUN dnf -y install java-17-openjdk-devel maven && yum clean all && rm -rf /var/cache/yum/*
RUN alternatives --set java $(alternatives --display java | grep 'family java-17-openjdk' | cut -d' ' -f1)
RUN alternatives --set javac $(alternatives --display javac | grep 'family java-17-openjdk' | cut -d' ' -f1)
RUN dnf -y install java-21-openjdk-devel maven && yum clean all && rm -rf /var/cache/yum/*
RUN alternatives --set java $(alternatives --display java | grep 'family java-21-openjdk' | cut -d' ' -f1)
RUN alternatives --set javac $(alternatives --display javac | grep 'family java-21-openjdk' | cut -d' ' -f1)
RUN mkdir /build
ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk
1 change: 0 additions & 1 deletion build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ From root of repo:

```
docker run --rm -it -v $(pwd):/build -w /build \
-e JAVA_HOME=/usr/lib/jvm/java-17-openjdk \
osc-keycloak-scripts-build:latest mvn clean package
```
16 changes: 16 additions & 0 deletions csm-authenticator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

function authenticate(context) {

LOG.info(script.name + " --> trace auth for: " + user.username);

const allowed = /(REQAPPROVAL|ACTIVE|WEBONLY|RESTRICTED)/;
if (user.getFirstAttribute("employeeStatus") && allowed.test(user.getFirstAttribute("employeeStatus"))) {
context.success();
} else {
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}

context.success();
}
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

<groupId>edu.osc</groupId>
<artifactId>osc-keycloak-scripts</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<packaging>jar</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>17.0.0</java.version>
<java.version>21.0.0</java.version>
</properties>

<dependencies>
Expand All @@ -23,7 +23,7 @@
</dependencies>

<build>
<finalName>osc-keycloak-scripts</finalName>
<finalName>osc-keycloak-scripts-${project.version}</finalName>
<resources>
<resource>
<directory>.</directory>
Expand Down
13 changes: 13 additions & 0 deletions user-enabled-authenticator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError");

function authenticate(context) {

LOG.info(script.name + " --> trace auth for: " + user.username);

if (user.getFirstAttribute("nsAccountLock") == "TRUE" || user.getFirstAttribute("loginDisabled") == "TRUE") {
context.failure(AuthenticationFlowError.INVALID_USER);
return;
}

context.success();
}

0 comments on commit fbe70b1

Please sign in to comment.