Commit 9987dc3b authored by Moritz Schlarb's avatar Moritz Schlarb

Merge tag 'upstream/2.3.3'

Upstream version 2.3.3
parents 2184de8e 99f94b06
...@@ -38,3 +38,5 @@ reporting bugs, providing fixes, suggesting useful features or other: ...@@ -38,3 +38,5 @@ reporting bugs, providing fixes, suggesting useful features or other:
Moritz Schlarb <https://github.com/moschlar> Moritz Schlarb <https://github.com/moschlar>
remi-cc <https://github.com/remi-cc> remi-cc <https://github.com/remi-cc>
hihellobolke <https://github.com/hihellobolke> hihellobolke <https://github.com/hihellobolke>
Horatiu Eugen Vlad <https://github.com/iconoeugen>
cristichiru <https://github.com/cristichiru>
11/16/2017
- add support for passing userinfo as a JSON object or JWT; see #311
- release 2.3.3
11/13/2017
- add support for authentication to the introspection endpoint with a bearer token using OIDCOAuthIntrospectionClientAuthBearerToken; thanks @cristichiru
- bump to 2.3.3rc3
11/08/2017
- address a number of static code analysis issues
- bump to 2.3.3rc2
10/10/2017
- avoid crash when no scheme is set on OIDCProviderMetadataURL; closes #303; thanks @iconoeugen
- bump to 2.3.3rc1
10/6/2017
- avoid crash when no OIDCOAuthClientID is set for remote access token validation
- don't enforce "iat" slack checks on locally validaed JWT access tokens
- bump to 2.3.3rc0
09/18/2017 09/18/2017
- release 2.3.2 - release 2.3.2
...@@ -159,7 +180,7 @@ ...@@ -159,7 +180,7 @@
03/30/2017 03/30/2017
- merge feature branch back to master: - merge feature branch back to master:
- better support for Single Page Applications, see: - better support for Single Page Applications, see:
https://github.com/pingidentity/mod_auth_openidc/wiki/Single-Page-Applications https://github.com/zmartzone/mod_auth_openidc/wiki/Single-Page-Applications
- add session info hook that is configurable through OIDCInfoHook - add session info hook that is configurable through OIDCInfoHook
- add "AuthType auth-openidc" option that allows both "oauth20" and "openid-connect" on the same path - add "AuthType auth-openidc" option that allows both "oauth20" and "openid-connect" on the same path
- add encryption for all cache entries instead of just session data through OIDCCacheEncrypt - add encryption for all cache entries instead of just session data through OIDCCacheEncrypt
......
Preferably you should use one of the pre-compiled binary packages, available for Preferably you should use one of the pre-compiled binary packages, available for
various platforms, see: various platforms, see:
https://github.com/pingidentity/mod_auth_openidc/wiki#11-where-can-i-get-binary-packages https://github.com/zmartzone/mod_auth_openidc/wiki#11-where-can-i-get-binary-packages
and proceed with the Configuration section below. and proceed with the Configuration section below.
If your platform is not supported or you want to run the latest code, If your platform is not supported or you want to run the latest code,
......
[![Build Status](https://travis-ci.org/pingidentity/mod_auth_openidc.svg?branch=master)](https://travis-ci.org/pingidentity/mod_auth_openidc) [![Build Status](https://travis-ci.org/zmartzone/mod_auth_openidc.svg?branch=master)](https://travis-ci.org/zmartzone/mod_auth_openidc)
mod_auth_openidc mod_auth_openidc
================ ================
...@@ -35,14 +35,14 @@ of claims provided in the `id_token`/ `userinfo` claims. ...@@ -35,14 +35,14 @@ of claims provided in the `id_token`/ `userinfo` claims.
- [OpenID Provider Discovery](http://openid.net/specs/openid-connect-discovery-1_0.html) - [OpenID Provider Discovery](http://openid.net/specs/openid-connect-discovery-1_0.html)
- [OAuth 2.0 Form Post Response Mode](http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html) - [OAuth 2.0 Form Post Response Mode](http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)
- [Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636) - [Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636)
- [OpenID Connect Session Management](http://openid.net/specs/openid-connect-session-1_0.html). See the [Wiki](https://github.com/pingidentity/mod_auth_openidc/wiki/Session-Management) for information - [OpenID Connect Session Management](http://openid.net/specs/openid-connect-session-1_0.html). See the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/Session-Management) for information
on how to configure it. on how to configure it.
Alternatively the module can operate as an OAuth 2.0 Resource Server to an OAuth 2.0 Authorization Server, Alternatively the module can operate as an OAuth 2.0 Resource Server to an OAuth 2.0 Authorization Server,
introspecting/validating bearer Access Tokens conforming to [OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662) (or similar), introspecting/validating bearer Access Tokens conforming to [OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662) (or similar),
or verifiying them locally if they are JWTs. or verifiying them locally if they are JWTs.
The `REMOTE_USER` variable setting, passing claims in HTTP headers and authorization based on `Require` primitives The `REMOTE_USER` variable setting, passing claims in HTTP headers and authorization based on `Require` primitives
works in the same way as described for OpenID Connect above. See the [Wiki](https://github.com/pingidentity/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server) for information works in the same way as described for OpenID Connect above. See the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server) for information
on how to configure it. on how to configure it.
For an exhaustive description of all configuration options, see the file `auth_openidc.conf` For an exhaustive description of all configuration options, see the file `auth_openidc.conf`
...@@ -83,7 +83,7 @@ Require claim hd:<your-domain> ...@@ -83,7 +83,7 @@ Require claim hd:<your-domain>
``` ```
The above is an authorization example of an exact match of a provided claim against a string value. The above is an authorization example of an exact match of a provided claim against a string value.
For more authorization options see the [Wiki page on Authorization](https://github.com/pingidentity/mod_auth_openidc/wiki/Authorization). For more authorization options see the [Wiki page on Authorization](https://github.com/zmartzone/mod_auth_openidc/wiki/Authorization).
### Quickstart with a generic OpenID Connect Provider ### Quickstart with a generic OpenID Connect Provider
...@@ -110,7 +110,7 @@ OIDCCryptoPassphrase <password> ...@@ -110,7 +110,7 @@ OIDCCryptoPassphrase <password>
Require valid-user Require valid-user
</Location> </Location>
``` ```
For details on configuring multiple providers see the [Wiki](https://github.com/pingidentity/mod_auth_openidc/wiki/Multiple-Providers). For details on configuring multiple providers see the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/Multiple-Providers).
### PingFederate OAuth 2.0 Resource Server ### PingFederate OAuth 2.0 Resource Server
...@@ -134,7 +134,7 @@ OIDCOAuthClientSecret 2Federate ...@@ -134,7 +134,7 @@ OIDCOAuthClientSecret 2Federate
#Require claim scope~\bprofile\b #Require claim scope~\bprofile\b
</Location> </Location>
``` ```
For details and additional options on the OAuth 2.0 Resource Server setup see the [Wiki](https://github.com/pingidentity/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server). For details and additional options on the OAuth 2.0 Resource Server setup see the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server).
### Quickstart with a generic OAuth 2.0 Resource Server ### Quickstart with a generic OAuth 2.0 Resource Server
...@@ -142,7 +142,7 @@ Using "local" validation of JWT bearer tokens: ...@@ -142,7 +142,7 @@ Using "local" validation of JWT bearer tokens:
1. install and load `mod_auth_openidc.so` in your Apache server 1. install and load `mod_auth_openidc.so` in your Apache server
1. configure your protected APIs/locations with `AuthType oauth20` and `Require claim` directives to restrict access to specific clients/scopes/claims/resource-owners 1. configure your protected APIs/locations with `AuthType oauth20` and `Require claim` directives to restrict access to specific clients/scopes/claims/resource-owners
1. configure local or remote bearer token validation following the [Wiki](https://github.com/pingidentity/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server) 1. configure local or remote bearer token validation following the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server)
```apache ```apache
# local validation # local validation
...@@ -158,7 +158,7 @@ Support ...@@ -158,7 +158,7 @@ Support
------- -------
See the Wiki pages with Frequently Asked Questions at: See the Wiki pages with Frequently Asked Questions at:
https://github.com/pingidentity/mod_auth_openidc/wiki https://github.com/zmartzone/mod_auth_openidc/wiki
There is a Google Group/mailing list at: There is a Google Group/mailing list at:
[mod_auth_openidc@googlegroups.com](mailto:mod_auth_openidc@googlegroups.com) [mod_auth_openidc@googlegroups.com](mailto:mod_auth_openidc@googlegroups.com)
The corresponding forum/archive is at: The corresponding forum/archive is at:
...@@ -173,6 +173,5 @@ The Github issues tracker should be used only for bugs reports and feature reque ...@@ -173,6 +173,5 @@ The Github issues tracker should be used only for bugs reports and feature reque
Disclaimer Disclaimer
---------- ----------
*This software is open sourced by Ping Identity but not supported commercially *This software is open sourced by ZmartZone IAM. For commercial support
by Ping Identity, see also the DISCLAIMER file in this directory. For commercial support
you can contact [ZmartZone IAM](https://www.zmartzone.eu) as described above.* you can contact [ZmartZone IAM](https://www.zmartzone.eu) as described above.*
...@@ -289,6 +289,12 @@ ...@@ -289,6 +289,12 @@
# When not defined "client_secret_basic" is used. # When not defined "client_secret_basic" is used.
#OIDCOAuthIntrospectionEndpointAuth [ client_secret_basic | client_secret_post | client_secret_jwt | private_key_jwt] #OIDCOAuthIntrospectionEndpointAuth [ client_secret_basic | client_secret_post | client_secret_jwt | private_key_jwt]
# Some OP do not accept basic or post, only bearer tokens in the Authorization header.
# Specify here a static token to be used for authorizing the call to the introspection endpoint.
# If empty, the introspected token will be used for authorization as well.
# If unset, one of the methods specified by OIDCOAuthIntrospectionEndpointAuth will be used.
#OIDCOAuthIntrospectionClientAuthBearerToken [ a-static-bearer-token | ]
# Filename that contains the PEM-formatted client certificate used to authenticate the # Filename that contains the PEM-formatted client certificate used to authenticate the
# caller in token introspection calls to the OAuth 2.0 Authorization server. # caller in token introspection calls to the OAuth 2.0 Authorization server.
#OIDCOAuthIntrospectionEndpointCert <filename> #OIDCOAuthIntrospectionEndpointCert <filename>
...@@ -636,6 +642,14 @@ ...@@ -636,6 +642,14 @@
# When not defined the default "claims" is used. # When not defined the default "claims" is used.
#OIDCPassIDTokenAs [claims|payload|serialized]+ #OIDCPassIDTokenAs [claims|payload|serialized]+
# Define the way(s) in which the claims resolved from the userinfo endpoint are passed to the application according to OIDCPassClaimsAs.
# Must be one or several of:
# "claims" : the userinfo claims are passed in individual headers/environment variables
# "json" : a self-contained userinfo JSON object is passed in the "OIDC_userinfo_json" header/environment variable
# "jwt" : a signed/encrypted JWT (if available!) optionally resolved from the userinfo endpoint is passed in the "OIDC_userinfo_jwt" header/environment variable
# When not defined the default "claims" is used.
#OIDCPassUserInfoAs [claims|json|jwt]+
# Define the way in which the claims and tokens are passed to the application environment: # Define the way in which the claims and tokens are passed to the application environment:
# "none": no claims/tokens are passed # "none": no claims/tokens are passed
# "environment": claims/tokens are passed as environment variables # "environment": claims/tokens are passed as environment variables
...@@ -702,7 +716,7 @@ ...@@ -702,7 +716,7 @@
#OIDCPassRefreshToken [On|Off] #OIDCPassRefreshToken [On|Off]
# Request Object/URI settings expressed as a string that is a "double-quote-escaped" JSON object. For example: # Request Object/URI settings expressed as a string that is a "double-quote-escaped" JSON object. For example:
# "{ \"copy_from_request\": [ \"claims\", \"response_type\", \"response_mode\", \"login_hint\", \"id_token_hint\", \"nonce\", \"state\", \"redirect_uri\", \"scope\", \"client_id\" ], \"static\": { \"some\": \"value\", \"some_nested\": { \"some_array\": [ 1,2,3] } }, \"crypto\": { \"sign_alg\": \"HS256\", \"crypt_alg\": \"A256KW\", \"crypt_enc\": \"A256CBC-HS512\" }, \"url\": \"https://www.pingidentity.nl/protected/\", \"request_object_type\" : \"request\" }" # "{ \"copy_from_request\": [ \"claims\", \"response_type\", \"response_mode\", \"login_hint\", \"id_token_hint\", \"nonce\", \"state\", \"redirect_uri\", \"scope\", \"client_id\" ], \"static\": { \"some\": \"value\", \"some_nested\": { \"some_array\": [ 1,2,3] } }, \"crypto\": { \"sign_alg\": \"HS256\", \"crypt_alg\": \"A256KW\", \"crypt_enc\": \"A256CBC-HS512\" }, \"url\": \"https://www.zmartzone.eu/protected/\", \"request_object_type\" : \"request\" }"
# Parameters: # Parameters:
# copy_from_request (array) : array of query parameter names copied from request # copy_from_request (array) : array of query parameter names copied from request
# copy_and_remove_from_request (array) : array of parameter names copied from request and removed as query parameter # copy_and_remove_from_request (array) : array of parameter names copied from request and removed as query parameter
......
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for mod_auth_openidc 2.3.2. # Generated by GNU Autoconf 2.69 for mod_auth_openidc 2.3.3.
# #
# Report bugs to <hans.zandbelt@zmartzone.eu>. # Report bugs to <hans.zandbelt@zmartzone.eu>.
# #
...@@ -580,8 +580,8 @@ MAKEFLAGS= ...@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='mod_auth_openidc' PACKAGE_NAME='mod_auth_openidc'
PACKAGE_TARNAME='mod_auth_openidc' PACKAGE_TARNAME='mod_auth_openidc'
PACKAGE_VERSION='2.3.2' PACKAGE_VERSION='2.3.3'
PACKAGE_STRING='mod_auth_openidc 2.3.2' PACKAGE_STRING='mod_auth_openidc 2.3.3'
PACKAGE_BUGREPORT='hans.zandbelt@zmartzone.eu' PACKAGE_BUGREPORT='hans.zandbelt@zmartzone.eu'
PACKAGE_URL='' PACKAGE_URL=''
...@@ -1269,7 +1269,7 @@ if test "$ac_init_help" = "long"; then ...@@ -1269,7 +1269,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures mod_auth_openidc 2.3.2 to adapt to many kinds of systems. \`configure' configures mod_auth_openidc 2.3.3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
...@@ -1331,7 +1331,7 @@ fi ...@@ -1331,7 +1331,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of mod_auth_openidc 2.3.2:";; short | recursive ) echo "Configuration of mod_auth_openidc 2.3.3:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
...@@ -1445,7 +1445,7 @@ fi ...@@ -1445,7 +1445,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
mod_auth_openidc configure 2.3.2 mod_auth_openidc configure 2.3.3
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
...@@ -1747,7 +1747,7 @@ cat >config.log <<_ACEOF ...@@ -1747,7 +1747,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by mod_auth_openidc $as_me 2.3.2, which was It was created by mod_auth_openidc $as_me 2.3.3, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
...@@ -2096,7 +2096,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ...@@ -2096,7 +2096,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
NAMEVER=mod_auth_openidc-2.3.2 NAMEVER=mod_auth_openidc-2.3.3
# This section defines the --with-apxs2 option. # This section defines the --with-apxs2 option.
...@@ -4886,7 +4886,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ...@@ -4886,7 +4886,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by mod_auth_openidc $as_me 2.3.2, which was This file was extended by mod_auth_openidc $as_me 2.3.3, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
...@@ -4939,7 +4939,7 @@ _ACEOF ...@@ -4939,7 +4939,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
mod_auth_openidc config.status 2.3.2 mod_auth_openidc config.status 2.3.3
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"
......
AC_INIT([mod_auth_openidc],[2.3.2],[hans.zandbelt@zmartzone.eu]) AC_INIT([mod_auth_openidc],[2.3.3],[hans.zandbelt@zmartzone.eu])
AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION()) AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION())
......
...@@ -207,8 +207,10 @@ ...@@ -207,8 +207,10 @@
#define OIDCCryptoPassphrase "OIDCCryptoPassphrase" #define OIDCCryptoPassphrase "OIDCCryptoPassphrase"
#define OIDCClaimDelimiter "OIDCClaimDelimiter" #define OIDCClaimDelimiter "OIDCClaimDelimiter"
#define OIDCPassIDTokenAs "OIDCPassIDTokenAs" #define OIDCPassIDTokenAs "OIDCPassIDTokenAs"
#define OIDCPassUserInfoAs "OIDCPassUserInfoAs"
#define OIDCOAuthClientID "OIDCOAuthClientID" #define OIDCOAuthClientID "OIDCOAuthClientID"
#define OIDCOAuthClientSecret "OIDCOAuthClientSecret" #define OIDCOAuthClientSecret "OIDCOAuthClientSecret"
#define OIDCOAuthIntrospectionClientAuthBearerToken "OIDCOAuthIntrospectionClientAuthBearerToken"
#define OIDCOAuthIntrospectionEndpoint "OIDCOAuthIntrospectionEndpoint" #define OIDCOAuthIntrospectionEndpoint "OIDCOAuthIntrospectionEndpoint"
#define OIDCOAuthIntrospectionEndpointMethod "OIDCOAuthIntrospectionEndpointMethod" #define OIDCOAuthIntrospectionEndpointMethod "OIDCOAuthIntrospectionEndpointMethod"
#define OIDCOAuthIntrospectionEndpointParams "OIDCOAuthIntrospectionEndpointParams" #define OIDCOAuthIntrospectionEndpointParams "OIDCOAuthIntrospectionEndpointParams"
...@@ -719,6 +721,18 @@ static const char * oidc_set_pass_idtoken_as(cmd_parms *cmd, void *dummy, ...@@ -719,6 +721,18 @@ static const char * oidc_set_pass_idtoken_as(cmd_parms *cmd, void *dummy,
return OIDC_CONFIG_DIR_RV(cmd, rv); return OIDC_CONFIG_DIR_RV(cmd, rv);
} }
/*
* define how to pass the userinfo/claims in HTTP headers
*/
static const char * oidc_set_pass_userinfo_as(cmd_parms *cmd, void *dummy,
const char *v1, const char *v2, const char *v3) {
oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(
cmd->server->module_config, &auth_openidc_module);
const char *rv = oidc_parse_pass_userinfo_as(cmd->pool, v1, v2, v3,
&cfg->pass_userinfo_as);
return OIDC_CONFIG_DIR_RV(cmd, rv);
}
/* /*
* define which method of pass an OAuth Bearer token is accepted * define which method of pass an OAuth Bearer token is accepted
*/ */
...@@ -965,6 +979,19 @@ const char *oidc_set_auth_request_method(cmd_parms *cmd, void *struct_ptr, ...@@ -965,6 +979,19 @@ const char *oidc_set_auth_request_method(cmd_parms *cmd, void *struct_ptr,
return OIDC_CONFIG_DIR_RV(cmd, rv); return OIDC_CONFIG_DIR_RV(cmd, rv);
} }
/*
* set the introspection authorization static bearer token
*/
static const char *oidc_set_client_auth_bearer_token(cmd_parms *cmd,
void *struct_ptr, const char *args) {
oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(
cmd->server->module_config, &auth_openidc_module);
char *w = ap_getword_conf(cmd->pool, &args);
cfg->oauth.introspection_client_auth_bearer_token =
(*w == '\0' || *args != 0) ? "" : w;
return NULL;
}
/* /*
* create a new server config record with defaults * create a new server config record with defaults
*/ */
...@@ -1028,6 +1055,7 @@ void *oidc_create_server_config(apr_pool_t *pool, server_rec *svr) { ...@@ -1028,6 +1055,7 @@ void *oidc_create_server_config(apr_pool_t *pool, server_rec *svr) {
c->oauth.introspection_endpoint_method = OIDC_DEFAULT_OAUTH_ENDPOINT_METHOD; c->oauth.introspection_endpoint_method = OIDC_DEFAULT_OAUTH_ENDPOINT_METHOD;
c->oauth.introspection_endpoint_params = NULL; c->oauth.introspection_endpoint_params = NULL;
c->oauth.introspection_endpoint_auth = NULL; c->oauth.introspection_endpoint_auth = NULL;
c->oauth.introspection_client_auth_bearer_token = NULL;
c->oauth.introspection_token_param_name = c->oauth.introspection_token_param_name =
OIDC_DEFAULT_OAUTH_TOKEN_PARAM_NAME; OIDC_DEFAULT_OAUTH_TOKEN_PARAM_NAME;
...@@ -1080,6 +1108,7 @@ void *oidc_create_server_config(apr_pool_t *pool, server_rec *svr) { ...@@ -1080,6 +1108,7 @@ void *oidc_create_server_config(apr_pool_t *pool, server_rec *svr) {
c->remote_user_claim.reg_exp = NULL; c->remote_user_claim.reg_exp = NULL;
c->remote_user_claim.replace = NULL; c->remote_user_claim.replace = NULL;
c->pass_idtoken_as = OIDC_PASS_IDTOKEN_AS_CLAIMS; c->pass_idtoken_as = OIDC_PASS_IDTOKEN_AS_CLAIMS;
c->pass_userinfo_as = OIDC_PASS_USERINFO_AS_CLAIMS;
c->cookie_http_only = OIDC_DEFAULT_COOKIE_HTTPONLY; c->cookie_http_only = OIDC_DEFAULT_COOKIE_HTTPONLY;
c->cookie_same_site = OIDC_DEFAULT_COOKIE_SAME_SITE; c->cookie_same_site = OIDC_DEFAULT_COOKIE_SAME_SITE;
...@@ -1320,6 +1349,10 @@ void *oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) { ...@@ -1320,6 +1349,10 @@ void *oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) {
add->oauth.introspection_endpoint_auth != NULL ? add->oauth.introspection_endpoint_auth != NULL ?
add->oauth.introspection_endpoint_auth : add->oauth.introspection_endpoint_auth :
base->oauth.introspection_endpoint_auth; base->oauth.introspection_endpoint_auth;
c->oauth.introspection_client_auth_bearer_token =
add->oauth.introspection_client_auth_bearer_token != NULL ?
add->oauth.introspection_client_auth_bearer_token :
base->oauth.introspection_client_auth_bearer_token;
c->oauth.introspection_token_param_name = c->oauth.introspection_token_param_name =
apr_strnatcmp(add->oauth.introspection_token_param_name, apr_strnatcmp(add->oauth.introspection_token_param_name,
OIDC_DEFAULT_OAUTH_TOKEN_PARAM_NAME) != 0 ? OIDC_DEFAULT_OAUTH_TOKEN_PARAM_NAME) != 0 ?
...@@ -1468,6 +1501,9 @@ void *oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) { ...@@ -1468,6 +1501,9 @@ void *oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) {
c->pass_idtoken_as = c->pass_idtoken_as =
add->pass_idtoken_as != OIDC_PASS_IDTOKEN_AS_CLAIMS ? add->pass_idtoken_as != OIDC_PASS_IDTOKEN_AS_CLAIMS ?
add->pass_idtoken_as : base->pass_idtoken_as; add->pass_idtoken_as : base->pass_idtoken_as;
c->pass_userinfo_as =
add->pass_userinfo_as != OIDC_PASS_USERINFO_AS_CLAIMS ?
add->pass_userinfo_as : base->pass_userinfo_as;
c->cookie_http_only = c->cookie_http_only =
add->cookie_http_only != OIDC_DEFAULT_COOKIE_HTTPONLY ? add->cookie_http_only != OIDC_DEFAULT_COOKIE_HTTPONLY ?
add->cookie_http_only : base->cookie_http_only; add->cookie_http_only : base->cookie_http_only;
...@@ -1615,7 +1651,7 @@ char *oidc_cfg_dir_authn_header(request_rec *r) { ...@@ -1615,7 +1651,7 @@ char *oidc_cfg_dir_authn_header(request_rec *r) {
return dir_cfg->authn_header; return dir_cfg->authn_header;
} }
int oidc_cfg_dir_pass_info_in_headers(request_rec *r) { apr_byte_t oidc_cfg_dir_pass_info_in_headers(request_rec *r) {
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config, oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
&auth_openidc_module); &auth_openidc_module);
if (dir_cfg->pass_info_in_headers == OIDC_CONFIG_POS_INT_UNSET) if (dir_cfg->pass_info_in_headers == OIDC_CONFIG_POS_INT_UNSET)
...@@ -1623,7 +1659,7 @@ int oidc_cfg_dir_pass_info_in_headers(request_rec *r) { ...@@ -1623,7 +1659,7 @@ int oidc_cfg_dir_pass_info_in_headers(request_rec *r) {
return dir_cfg->pass_info_in_headers; return dir_cfg->pass_info_in_headers;
} }
int oidc_cfg_dir_pass_info_in_envvars(request_rec *r) { apr_byte_t oidc_cfg_dir_pass_info_in_envvars(request_rec *r) {
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config, oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
&auth_openidc_module); &auth_openidc_module);
if (dir_cfg->pass_info_in_env_vars == OIDC_CONFIG_POS_INT_UNSET) if (dir_cfg->pass_info_in_env_vars == OIDC_CONFIG_POS_INT_UNSET)
...@@ -1631,7 +1667,7 @@ int oidc_cfg_dir_pass_info_in_envvars(request_rec *r) { ...@@ -1631,7 +1667,7 @@ int oidc_cfg_dir_pass_info_in_envvars(request_rec *r) {
return dir_cfg->pass_info_in_env_vars; return dir_cfg->pass_info_in_env_vars;
} }
int oidc_cfg_dir_pass_refresh_token(request_rec *r) { apr_byte_t oidc_cfg_dir_pass_refresh_token(request_rec *r) {
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config, oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
&auth_openidc_module); &auth_openidc_module);
if (dir_cfg->pass_refresh_token == OIDC_CONFIG_POS_INT_UNSET) if (dir_cfg->pass_refresh_token == OIDC_CONFIG_POS_INT_UNSET)
...@@ -1639,7 +1675,7 @@ int oidc_cfg_dir_pass_refresh_token(request_rec *r) { ...@@ -1639,7 +1675,7 @@ int oidc_cfg_dir_pass_refresh_token(request_rec *r) {
return dir_cfg->pass_refresh_token; return dir_cfg->pass_refresh_token;
} }
int oidc_cfg_dir_accept_token_in(request_rec *r) { apr_byte_t oidc_cfg_dir_accept_token_in(request_rec *r) {
oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config, oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
&auth_openidc_module); &auth_openidc_module);
if (dir_cfg->oauth_accept_token_in == OIDC_CONFIG_POS_INT_UNSET) if (dir_cfg->oauth_accept_token_in == OIDC_CONFIG_POS_INT_UNSET)
...@@ -1814,7 +1850,8 @@ static int oidc_check_config_openid_openidc(server_rec *s, oidc_cfg *c) { ...@@ -1814,7 +1850,8 @@ static int oidc_check_config_openid_openidc(server_rec *s, oidc_cfg *c) {
OIDCProviderAuthorizationEndpoint); OIDCProviderAuthorizationEndpoint);
} else { } else {
apr_uri_parse(s->process->pconf, c->provider.metadata_url, &r_uri); apr_uri_parse(s->process->pconf, c->provider.metadata_url, &r_uri);
if (apr_strnatcmp(r_uri.scheme, "http") == 0) { if ((r_uri.scheme == NULL)
|| (apr_strnatcmp(r_uri.scheme, "https") != 0)) {
oidc_swarn(s, oidc_swarn(s,
"the URL scheme (%s) of the configured " OIDCProviderMetadataURL " SHOULD be \"https\" for security reasons!", "the URL scheme (%s) of the configured " OIDCProviderMetadataURL " SHOULD be \"https\" for security reasons!",
r_uri.scheme); r_uri.scheme);
...@@ -2087,7 +2124,8 @@ static int oidc_post_config(apr_pool_t *pool, apr_pool_t *p1, apr_pool_t *p2, ...@@ -2087,7 +2124,8 @@ static int oidc_post_config(apr_pool_t *pool, apr_pool_t *p1, apr_pool_t *p2,
} }
#endif /* OPENSSL_NO_THREADID */ #endif /* OPENSSL_NO_THREADID */
#endif /* defined(OPENSSL_THREADS) && APR_HAS_THREADS */ #endif /* defined(OPENSSL_THREADS) && APR_HAS_THREADS */
apr_pool_cleanup_register(pool, s, oidc_cleanup_parent, apr_pool_cleanup_null); apr_pool_cleanup_register(pool, s, oidc_cleanup_parent,
apr_pool_cleanup_null);
server_rec *sp = s; server_rec *sp = s;
while (sp != NULL) { while (sp != NULL) {
...@@ -2149,7 +2187,7 @@ static void oidc_child_init(apr_pool_t *p, server_rec *s) { ...@@ -2149,7 +2187,7 @@ static void oidc_child_init(apr_pool_t *p, server_rec *s) {
} }
sp = sp->next; sp = sp->next;
} }
apr_pool_cleanup_register(p, s, oidc_cleanup_child, apr_pool_cleanup_null); apr_pool_cleanup_register(p, s, oidc_cleanup_child, apr_pool_cleanup_null);
} }
/* /*
...@@ -2201,7 +2239,7 @@ void oidc_register_hooks(apr_pool_t *pool) { ...@@ -2201,7 +2239,7 @@ void oidc_register_hooks(apr_pool_t *pool) {
const command_rec oidc_config_cmds[] = { const command_rec oidc_config_cmds[] = {
AP_INIT_TAKE1(OIDCProviderMetadataURL, AP_INIT_TAKE1(OIDCProviderMetadataURL,
oidc_set_string_slot, oidc_set_url_slot,
(void*)APR_OFFSETOF(oidc_cfg, provider.metadata_url), (void*)APR_OFFSETOF(oidc_cfg, provider.metadata_url),
RSRC_CONF, RSRC_CONF,
"OpenID Connect OP configuration metadata URL."), "OpenID Connect OP configuration metadata URL."),
...@@ -2461,6 +2499,11 @@ const command_rec oidc_config_cmds[] = { ...@@ -2461,6 +2499,11 @@ const command_rec oidc_config_cmds[] = {
NULL, NULL,
RSRC_CONF, RSRC_CONF,
"The format in which the id_token is passed in (a) header(s); must be one or more of: claims|payload|serialized"), "The format in which the id_token is passed in (a) header(s); must be one or more of: claims|payload|serialized"),
AP_INIT_TAKE123(OIDCPassUserInfoAs,
oidc_set_pass_userinfo_as,
NULL,
RSRC_CONF,
"The format in which the userinfo is passed in (a) header(s); must be one or more of: claims|json|jwt"),
AP_INIT_TAKE1(OIDCOAuthClientID, AP_INIT_TAKE1(OIDCOAuthClientID,
oidc_set_string_slot, oidc_set_string_slot,
...@@ -2494,6 +2537,11 @@ const command_rec oidc_config_cmds[] = { ...@@ -2494,6 +2537,11 @@ const command_rec oidc_config_cmds[] = {
(void *)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_auth), (void *)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_auth),
RSRC_CONF, RSRC_CONF,
"Specify an authentication method for the OAuth AS Introspection Endpoint (e.g.: client_secret_basic)"), "Specify an authentication method for the OAuth AS Introspection Endpoint (e.g.: client_secret_basic)"),
AP_INIT_RAW_ARGS(OIDCOAuthIntrospectionClientAuthBearerToken,
oidc_set_client_auth_bearer_token,
NULL,
RSRC_CONF,
"Specify a bearer token to authorize against the OAuth AS Introspection Endpoint (e.g.: 55554ee-2491-11e3-be72-001fe2e44345 or empty to use the introspected token itself)"),
AP_INIT_TAKE1(OIDCOAuthIntrospectionEndpointCert, AP_INIT_TAKE1(OIDCOAuthIntrospectionEndpointCert,
oidc_set_string_slot, oidc_set_string_slot,
(void*)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_tls_client_cert), (void*)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_tls_client_cert),
......
...@@ -188,7 +188,7 @@ int oidc_jwt_alg2kty(oidc_jwt_t *jwt) { ...@@ -188,7 +188,7 @@ int oidc_jwt_alg2kty(oidc_jwt_t *jwt) {
/* /*
* return the key size for an algorithm * return the key size for an algorithm
*/ */
int oidc_alg2keysize(const char *alg) { unsigned int oidc_alg2keysize(const char *alg) {
if (alg == NULL) if (alg == NULL)
return 0; return 0;
...@@ -738,6 +738,8 @@ apr_byte_t oidc_jwt_parse(apr_pool_t *pool, const char *input_json, ...@@ -738,6 +738,8 @@ apr_byte_t oidc_jwt_parse(apr_pool_t *pool, const char *input_json,
return FALSE; return FALSE;
*j_jwt = oidc_jwt_new(pool, FALSE, FALSE); *j_jwt = oidc_jwt_new(pool, FALSE, FALSE);
if (*j_jwt == NULL)
return FALSE;
oidc_jwt_t *jwt = *j_jwt; oidc_jwt_t *jwt = *j_jwt;
jwt->cjose_jws = cjose_jws_import(s_json, strlen(s_json), &cjose_err); jwt->cjose_jws = cjose_jws_import(s_json, strlen(s_json), &cjose_err);
......
...@@ -243,6 +243,6 @@ const char *oidc_jwt_hdr_get(oidc_jwt_t *jwt, const char *key); ...@@ -243,6 +243,6 @@ const char *oidc_jwt_hdr_get(oidc_jwt_t *jwt, const char *key);
/* return the key type of a JWT */ /* return the key type of a JWT */
int oidc_jwt_alg2kty(oidc_jwt_t *jwt); int oidc_jwt_alg2kty(oidc_jwt_t *jwt);
/* return the key size for an algorithm */ /* return the key size for an algorithm */
int oidc_alg2keysize(const char *alg); unsigned int oidc_alg2keysize(const char *alg);
#endif /* MOD_AUTH_OPENIDC_JOSE_H_ */ #endif /* MOD_AUTH_OPENIDC_JOSE_H_ */
...@@ -1272,11 +1272,11 @@ apr_byte_t oidc_metadata_client_parse(request_rec *r, oidc_cfg *cfg, ...@@ -1272,11 +1272,11 @@ apr_byte_t oidc_metadata_client_parse(request_rec *r, oidc_cfg *cfg,
if ((apr_strnatcmp(token_endpoint_auth, OIDC_PROTO_CLIENT_SECRET_POST) if ((apr_strnatcmp(token_endpoint_auth, OIDC_PROTO_CLIENT_SECRET_POST)
== 0) == 0)
|| (apr_strnatcmp(token_endpoint_auth, || (apr_strnatcmp(token_endpoint_auth,
OIDC_PROTO_CLIENT_SECRET_BASIC) == 0) OIDC_PROTO_CLIENT_SECRET_BASIC) == 0)
|| (apr_strnatcmp(token_endpoint_auth,
OIDC_PROTO_CLIENT_SECRET_JWT) == 0)
|| (apr_strnatcmp(token_endpoint_auth, || (apr_strnatcmp(token_endpoint_auth,
OIDC_PROTO_PRIVATE_KEY_JWT) == 0)) { OIDC_PROTO_CLIENT_SECRET_JWT) == 0)
|| (apr_strnatcmp(token_endpoint_auth,
OIDC_PROTO_PRIVATE_KEY_JWT) == 0)) {
provider->token_endpoint_auth = apr_pstrdup(r->pool, provider->token_endpoint_auth = apr_pstrdup(r->pool,
token_endpoint_auth); token_endpoint_auth);
} else { } else {
......
This diff is collapsed.
...@@ -123,11 +123,18 @@ APLOG_USE_MODULE(auth_openidc); ...@@ -123,11 +123,18 @@ APLOG_USE_MODULE(auth_openidc);
/* pass id_token as individual claims in headers (default) */ /* pass id_token as individual claims in headers (default) */
#define OIDC_PASS_IDTOKEN_AS_CLAIMS 1 #define OIDC_PASS_IDTOKEN_AS_CLAIMS 1
/* pass id_token payload as JSON object in header*/ /* pass id_token payload as JSON object in header */
#define OIDC_PASS_IDTOKEN_AS_PAYLOAD 2 #define OIDC_PASS_IDTOKEN_AS_PAYLOAD 2
/* pass id_token in compact serialized format in header*/ /* pass id_token in compact serialized format in header */
#define OIDC_PASS_IDTOKEN_AS_SERIALIZED 4 #define OIDC_PASS_IDTOKEN_AS_SERIALIZED 4
/* pass userinfo as individual claims in headers (default) */
#define OIDC_PASS_USERINFO_AS_CLAIMS 1
/* pass userinfo payload as JSON object in header */
#define OIDC_PASS_USERINFO_AS_JSON_OBJECT 2
/* pass userinfo as a JWT in header (when returned as a JWT) */
#define OIDC_PASS_USERINFO_AS_JWT 4
#define OIDC_OAUTH_ACCEPT_TOKEN_IN_DEFAULT 0 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_DEFAULT 0
/* accept bearer token in header (default) */ /* accept bearer token in header (default) */
#define OIDC_OAUTH_ACCEPT_TOKEN_IN_HEADER 1 #define OIDC_OAUTH_ACCEPT_TOKEN_IN_HEADER 1
...@@ -297,6 +304,7 @@ typedef struct oidc_oauth_t { ...@@ -297,6 +304,7 @@ typedef struct oidc_oauth_t {
char *introspection_endpoint_method; char *introspection_endpoint_method;
char *introspection_endpoint_params; char *introspection_endpoint_params;
char *introspection_endpoint_auth; char *introspection_endpoint_auth;
char *introspection_client_auth_bearer_token;
char *introspection_token_param_name; char *introspection_token_param_name;
char *introspection_token_expiry_claim_name; char *introspection_token_expiry_claim_name;
char *introspection_token_expiry_claim_format; char *introspection_token_expiry_claim_format;
...@@ -375,6 +383,7 @@ typedef struct oidc_cfg { ...@@ -375,6 +383,7 @@ typedef struct oidc_cfg {
char *claim_prefix; char *claim_prefix;
oidc_remote_user_claim_t remote_user_claim; oidc_remote_user_claim_t remote_user_claim;
int pass_idtoken_as; int pass_idtoken_as;
int pass_userinfo_as;
int cookie_http_only; int cookie_http_only;
int cookie_same_site; int cookie_same_site;
...@@ -550,6 +559,8 @@ apr_byte_t oidc_oauth_get_bearer_token(request_rec *r, const char **access_token ...@@ -550,6 +559,8 @@ apr_byte_t oidc_oauth_get_bearer_token(request_rec *r, const char **access_token
#define OIDC_APP_INFO_ACCESS_TOKEN_EXP "access_token_expires" #define OIDC_APP_INFO_ACCESS_TOKEN_EXP "access_token_expires"
#define OIDC_APP_INFO_ID_TOKEN "id_token" #define OIDC_APP_INFO_ID_TOKEN "id_token"
#define OIDC_APP_INFO_ID_TOKEN_PAYLOAD "id_token_payload" #define OIDC_APP_INFO_ID_TOKEN_PAYLOAD "id_token_payload"
#define OIDC_APP_INFO_USERINFO_JSON "userinfo_json"
#define OIDC_APP_INFO_USERINFO_JWT "userinfo_jwt"
typedef json_t oidc_proto_state_t; typedef json_t oidc_proto_state_t;
...@@ -580,14 +591,14 @@ void oidc_proto_state_set_prompt(oidc_proto_state_t *proto_state, const char *pr ...@@ -580,14 +591,14 @@ void oidc_proto_state_set_prompt(oidc_proto_state_t *proto_state, const char *pr
void oidc_proto_state_set_pkce_state(oidc_proto_state_t *proto_state, const char *pkce_state); void oidc_proto_state_set_pkce_state(oidc_proto_state_t *proto_state, const char *pkce_state);
void oidc_proto_state_set_timestamp_now(oidc_proto_state_t *proto_state); void oidc_proto_state_set_timestamp_now(oidc_proto_state_t *proto_state);
apr_byte_t oidc_proto_token_endpoint_auth(request_rec *r, oidc_cfg *cfg, const char *token_endpoint_auth, const char *client_id, const char *client_secret, const char *audience, apr_table_t *params, char **basic_auth_str); apr_byte_t oidc_proto_token_endpoint_auth(request_rec *r, oidc_cfg *cfg, const char *token_endpoint_auth, const char *client_id, const char *client_secret, const char *audience, apr_table_t *params, char **basic_auth_str, char **bearer_auth_str);
char *oidc_proto_peek_jwt_header(request_rec *r, const char *jwt, char **alg); char *oidc_proto_peek_jwt_header(request_rec *r, const char *jwt, char **alg);
int oidc_proto_authorization_request(request_rec *r, struct oidc_provider_t *provider, const char *login_hint, const char *redirect_uri, const char *state, oidc_proto_state_t *proto_state, const char *id_token_hint, const char *code_challenge, const char *auth_request_params, const char *path_scope); int oidc_proto_authorization_request(request_rec *r, struct oidc_provider_t *provider, const char *login_hint, const char *redirect_uri, const char *state, oidc_proto_state_t *proto_state, const char *id_token_hint, const char *code_challenge, const char *auth_request_params, const char *path_scope);
apr_byte_t oidc_proto_is_post_authorization_response(request_rec *r, oidc_cfg *cfg); apr_byte_t oidc_proto_is_post_authorization_response(request_rec *r, oidc_cfg *cfg);
apr_byte_t oidc_proto_is_redirect_authorization_response(request_rec *r, oidc_cfg *cfg); apr_byte_t oidc_proto_is_redirect_authorization_response(request_rec *r, oidc_cfg *cfg