Skip to content

Commit

Permalink
add JWT handler wih optional JQ filtering
Browse files Browse the repository at this point in the history
depend on liboauth2 >= 2.1.0; bump to 4.1.0dev

Signed-off-by: Hans Zandbelt <hans.zandbelt@openidc.com>
  • Loading branch information
zandbelt committed Sep 13, 2024
1 parent db142c3 commit 2dd81b7
Show file tree
Hide file tree
Showing 11 changed files with 411 additions and 36 deletions.
19 changes: 9 additions & 10 deletions .cproject
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.Cygwin_PE" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.PE64" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.Cygwin_PE64" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
Expand All @@ -18,7 +18,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.linuxtools.cdt.autotools.core.buildArtefactType.autotools" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.linuxtools.cdt.autotools.core.buildArtefactType.autotools,org.eclipse.cdt.build.core.buildType=org.eclipse.linuxtools.cdt.autotools.core.buildType.default" cleanCommand="rm -rf" description="" errorParsers="org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="org.eclipse.linuxtools.cdt.autotools.core.configuration.build.1562680719" name="Build (GNU)" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.connection=unix:///var/run/docker.sock" parent="org.eclipse.linuxtools.cdt.autotools.core.configuration.build">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.linuxtools.cdt.autotools.core.buildArtefactType.autotools" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.linuxtools.cdt.autotools.core.buildArtefactType.autotools,org.eclipse.cdt.build.core.buildType=org.eclipse.linuxtools.cdt.autotools.core.buildType.default" cleanCommand="rm -rf" description="" errorParsers="org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.GASErrorParser" id="org.eclipse.linuxtools.cdt.autotools.core.configuration.build.1562680719" name="Build (GNU)" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.connection=unix:///var/run/docker.sock,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=" parent="org.eclipse.linuxtools.cdt.autotools.core.configuration.build">
<folderInfo id="org.eclipse.linuxtools.cdt.autotools.core.configuration.build.1562680719." name="/" resourcePath="">
<toolChain id="org.eclipse.linuxtools.cdt.autotools.core.toolChain.617277945" name="GNU Autotools Toolchain" superClass="org.eclipse.linuxtools.cdt.autotools.core.toolChain">
<targetPlatform id="org.eclipse.linuxtools.cdt.autotools.core.toolchain.targetPlatform.359991688" isAbstract="false" name="GNU Autotools Target Platform" superClass="org.eclipse.linuxtools.cdt.autotools.core.toolchain.targetPlatform"/>
Expand Down Expand Up @@ -53,10 +53,10 @@
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.MachO64" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.Cygwin_PE" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.PE" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.PE64" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.Cygwin_PE64" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
Expand Down Expand Up @@ -117,29 +117,28 @@
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
<buildTargets>
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<target name="check" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildTarget>all</buildTarget>
<buildArguments/>
<buildTarget>check</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clang-format" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clang-format</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
</cproject>
</cproject>
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
/liboauth2_sts.la
/test-suite.log
/.settings
/configure~
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
09/13/2024
- add JWT handler wih optional JQ filtering
- depend on liboauth2 >= 2.1.0
- bump to 4.1.0dev

08/22/2024
- change LICENSE to Apache 2.0
- depend on liboauth2 >= 2.0.0
Expand Down
6 changes: 3 additions & 3 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ liboauth2_sts_la_SOURCES = \
src/sts.c \
src/wstrust.c \
src/ropc.c \
src/otx.c
src/otx.c \
src/jwt.c

if HAVE_CHECK

Expand All @@ -34,8 +35,7 @@ check_liboauth2_sts_SOURCES = \
test/check_liboauth2_sts.c

check_liboauth2_sts_CFLAGS = $(AM_CFLAGS) @CHECK_CFLAGS@
check_liboauth2_sts_LDADD = @CHECK_LIBS@

check_liboauth2_sts_LDADD = liboauth2_sts.la @CHECK_LIBS@
endif


Expand Down
4 changes: 2 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
AC_INIT([liboauth2-sts],[4.0.0],[hans.zandbelt@openidc.com])
AC_INIT([liboauth2-sts],[4.1.0dev],[hans.zandbelt@openidc.com])

AM_INIT_AUTOMAKE([foreign no-define subdir-objects])
AC_CONFIG_MACRO_DIRS([m4])
Expand All @@ -13,7 +13,7 @@ PKG_CHECK_MODULES(XML, libxml-2.0 >= 2.4)
AC_SUBST(XML_CFLAGS)
AC_SUBST(XML_LIBS)

PKG_CHECK_MODULES(OAUTH2, liboauth2 >= 2.0.0)
PKG_CHECK_MODULES(OAUTH2, liboauth2 >= 2.1.0)
AC_SUBST(OAUTH2_CFLAGS)
AC_SUBST(OAUTH2_LIBS)

Expand Down
3 changes: 2 additions & 1 deletion include/oauth2/sts.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#define STS_TYPE_ROPC 2
#define STS_TYPE_OTX 3
#define STS_TYPE_CC 4
#define STS_TYPE_JWT 5

OAUTH2_CFG_TYPE_DECLARE(sts, cfg)

Expand All @@ -71,7 +72,7 @@ const char *sts_cfg_set_pass_target_token_in(oauth2_log_t *log,

const char *sts_cfg_set_exchange(oauth2_log_t *log, oauth2_sts_cfg_t *cfg,
const char *type, const char *url,
const char *options);
const char *options, const char *extra);

int sts_cfg_get_type(oauth2_sts_cfg_t *cfg);
oauth2_cfg_source_token_t *
Expand Down
16 changes: 0 additions & 16 deletions src/Makefile.am

This file was deleted.

171 changes: 171 additions & 0 deletions src/jwt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/***************************************************************************
*
* Copyright (C) 2018-2024 - ZmartZone Holding BV
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @Author: Hans Zandbelt - hans.zandbelt@openidc.com
*
**************************************************************************/

#include <stdlib.h>
#include <time.h>

#include <oauth2/http.h>
#include <oauth2/mem.h>
#include <oauth2/oauth2.h>
#include <oauth2/sts.h>
#ifdef OAUTH2_WITH_JQ
#include <oauth2/jq.h>
#endif

#include "sts_int.h"

static const char *sts_cfg_jwt_get_alg(oauth2_cfg_sts_t *cfg)
{
if (cfg->jwt_alg == NULL)
return CJOSE_HDR_ALG_RS256;
return cfg->jwt_alg;
}

oauth2_cache_t *sts_cfg_jwt_get_jq_cache(oauth2_log_t *log,
oauth2_sts_cfg_t *cfg)
{
oauth2_debug(log, "cfg->jwt_jq_cache=%p (name=%s)", cfg->jwt_jq_cache,
cfg->jwt_jq_cache_name);
if (cfg->jwt_jq_cache == NULL) {
cfg->jwt_jq_cache =
oauth2_cache_obtain(log, cfg->jwt_jq_cache_name);
}
return cfg->jwt_jq_cache;
}

const char *sts_cfg_set_jwt(oauth2_log_t *log, oauth2_sts_cfg_t *cfg,
const char *jwk, const oauth2_nv_list_t *params,
const char *expr)
{
char *rv = NULL;
cjose_err err;
char *cser = NULL;

err.code = CJOSE_ERR_NONE;

cfg->jwt_jwk = cjose_jwk_import(jwk, strlen(jwk), &err);
if (cfg->jwt_jwk == NULL) {
rv = oauth2_stradd(oauth2_strdup("cjose_jwk_import error: "),
jwk, " : ", err.message);
goto end;
}

cfg->jwt_alg = oauth2_strdup(oauth2_nv_list_get(log, params, "alg"));

cser = oauth2_jwt_create(log, cfg->jwt_jwk, sts_cfg_jwt_get_alg(cfg),
NULL, NULL, NULL, NULL, 0, false, false, NULL);
if (cser == NULL) {
rv = oauth2_stradd(NULL,
"could not create a signed JWT with the "
"configured JWK and algorithm: ",
sts_cfg_jwt_get_alg(cfg),
", make sure the JWK is a private key and "
"the alg value matches the key");
goto end;
}
oauth2_mem_free(cser);

cfg->jwt_iss = oauth2_strdup(oauth2_nv_list_get(log, params, "iss"));
cfg->jwt_sub = oauth2_strdup(oauth2_nv_list_get(log, params, "sub"));
cfg->jwt_client_id =
oauth2_strdup(oauth2_nv_list_get(log, params, "client_id"));
cfg->jwt_aud = oauth2_strdup(oauth2_nv_list_get(log, params, "aud"));

cfg->jwt_jq_expr = oauth2_strdup(expr);
if (cfg->jwt_jq_expr != NULL) {
#ifndef OAUTH2_WITH_JQ
rv = oauth2_strdup(
"a JQ expression is defined but JQ support is not compiled "
"into this version of liboauth2");
goto end;
#else
if (oauth2_jq_filter_compile(log, cfg->jwt_jq_expr, NULL) ==
false) {
rv = oauth2_stradd(
NULL, "could not compile the JQ expression: '",
cfg->jwt_jq_expr, "'");
goto end;
}
#endif
}

cfg->jwt_jq_cache_name =
oauth2_strdup(oauth2_nv_list_get(log, params, "jq.cache.name"));

cfg->jwt_jq_cache = oauth2_cache_obtain(log, cfg->jwt_jq_cache_name);
if (cfg->jwt_jq_cache == NULL)
rv = oauth2_stradd(NULL, "JQ cache: '", cfg->jwt_jq_cache_name,
"', could not be obtained, probably it is "
"not defined (yet)");

end:

return rv;
}

bool sts_jwt_exec(oauth2_log_t *log, oauth2_cfg_sts_t *cfg, const char *token,
char **rtoken, oauth2_uint_t *status_code)
{
bool rc = false;
json_t *payload = NULL;
oauth2_uint_t exp = 0;
bool include_iat = true;
bool include_jti = true;

oauth2_debug(log, "enter");

#ifdef OAUTH2_WITH_JQ
char *ftoken = NULL;
if (cfg->jwt_jq_expr != NULL) {
if (oauth2_jq_filter(log, sts_cfg_jwt_get_jq_cache(log, cfg),
token, cfg->jwt_jq_expr,
&ftoken) == false) {
oauth2_warn(log, "oauth2_jq_filter failed!");
} else {
token = ftoken;
}
}
#endif

if (oauth2_json_decode_object(log, token, &payload) == false)
goto end;

exp = (json_object_get(payload, OAUTH2_CLAIM_EXP) == NULL) ? 60 : 0;
include_iat = (json_object_get(payload, OAUTH2_CLAIM_IAT) == NULL);
include_jti = (json_object_get(payload, OAUTH2_CLAIM_JTI) == NULL);

*rtoken = oauth2_jwt_create(log, cfg->jwt_jwk, sts_cfg_jwt_get_alg(cfg),
cfg->jwt_iss, cfg->jwt_sub,
cfg->jwt_client_id, cfg->jwt_aud, exp,
include_iat, include_jti, payload);

rc = (*rtoken != NULL);

*status_code = rc ? 200 : 500;

end:

if (payload)
json_decref(payload);

oauth2_debug(log, "leave: %d", rc);

return rc;
}
Loading

0 comments on commit 2dd81b7

Please sign in to comment.