Skip to content

Commit

Permalink
first stab at FedCM support
Browse files Browse the repository at this point in the history
Signed-off-by: Hans Zandbelt <[email protected]>
  • Loading branch information
zandbelt committed May 8, 2024
1 parent da8718c commit 4be242a
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 3 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
05/08/2024
- initial support for the Federated Credential Management (FedCM) API
https://developers.google.com/privacy-sandbox/3pcd/fedcm

04/23/2024
- disable support for the RSA PKCS v1.5 JWE encryption algorithm as it is deemed unsafe
due to the Marvin attack and is removed from libcjose as well
Expand Down
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ libauth_openidc_la_SOURCES = \
src/handle/authz.c \
src/handle/content.c \
src/handle/discovery.c \
src/handle/fedcm.c \
src/handle/info.c \
src/handle/jwks.c \
src/handle/logout.c \
Expand Down
2 changes: 1 addition & 1 deletion auth_openidc.conf
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@
# "POST" means that the parameters will be passed as form-post parameters in an HTTP POST
# When not defined the default is "GET".
# NB: this can be overridden on a per-OP basis in the .conf file using the key: auth_request_method
# OIDCProviderAuthRequestMethod [ GET | POST ]
# OIDCProviderAuthRequestMethod [ GET | POST | FEDCM ]

# The fully qualified names of the files that contain the PEM-formatted RSA/EC Public key or a X.509 certificates
# that contain the RSA/EC public keys to be used for JWT (OP state/id_token) encryption by the OP.
Expand Down
8 changes: 6 additions & 2 deletions src/cfg/provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,15 @@ OIDC_PROVIDER_MEMBER_FUNCS_PARSE_STR(userinfo_encrypted_response_enc, oidc_cfg_p

#define OIDC_AUTH_REQUEST_METHOD_GET_STR "GET"
#define OIDC_AUTH_REQUEST_METHOD_POST_STR "POST"
#define OIDC_AUTH_REQUEST_METHOD_FEDCM_STR "FedCM"

static const char *oidc_cfg_provider_parse_auth_request_method(apr_pool_t *pool, const char *arg,
oidc_auth_request_method_t *method) {
static const oidc_cfg_option_t options[] = {{OIDC_AUTH_REQUEST_METHOD_GET, OIDC_AUTH_REQUEST_METHOD_GET_STR},
{OIDC_AUTH_REQUEST_METHOD_POST, OIDC_AUTH_REQUEST_METHOD_POST_STR}};
static const oidc_cfg_option_t options[] = {
{OIDC_AUTH_REQUEST_METHOD_GET, OIDC_AUTH_REQUEST_METHOD_GET_STR},
{OIDC_AUTH_REQUEST_METHOD_POST, OIDC_AUTH_REQUEST_METHOD_POST_STR},
{OIDC_AUTH_REQUEST_METHOD_FEDCM, OIDC_AUTH_REQUEST_METHOD_FEDCM_STR},
};
return oidc_cfg_parse_option(pool, options, OIDC_CFG_OPTIONS_SIZE(options), arg, (int *)method);
}

Expand Down
1 change: 1 addition & 0 deletions src/cfg/provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ typedef struct oidc_proto_pkce_t {
typedef enum {
OIDC_AUTH_REQUEST_METHOD_GET = 1,
OIDC_AUTH_REQUEST_METHOD_POST = 2,
OIDC_AUTH_REQUEST_METHOD_FEDCM = 3,
} oidc_auth_request_method_t;

typedef enum {
Expand Down
93 changes: 93 additions & 0 deletions src/handle/fedcm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

/***************************************************************************
* Copyright (C) 2017-2024 ZmartZone Holding BV
* All rights reserved.
*
* DISCLAIMER OF WARRANTIES:
*
* THE SOFTWARE PROVIDED HEREUNDER IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
* ANY WARRANTIES OR REPRESENTATIONS EXPRESS, IMPLIED OR STATUTORY; INCLUDING,
* WITHOUT LIMITATION, WARRANTIES OF QUALITY, PERFORMANCE, NONINFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. NOR ARE THERE ANY
* WARRANTIES CREATED BY A COURSE OR DEALING, COURSE OF PERFORMANCE OR TRADE
* USAGE. FURTHERMORE, THERE ARE NO WARRANTIES THAT THE SOFTWARE WILL MEET
* YOUR NEEDS OR BE FREE FROM ERRORS, OR THAT THE OPERATION OF THE SOFTWARE
* WILL BE UNINTERRUPTED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @Author: Hans Zandbelt - [email protected]
*/

#include "cfg/provider.h"
#include "handle/handle.h"
#include "proto.h"
#include "util.h"

int oidc_fedcm_request(request_rec *r, struct oidc_provider_t *provider, const char *redirect_uri, const char *state,
const char *nonce) {

oidc_debug(r, "enter");

const char *java_script = "<script type=\"text/javascript\">\n"
" async function signIn() {\n"
" const identityCredential = await navigator.credentials.get({\n"
" identity: {\n"
" providers: [\n"
" {\n"
" configURL: \"%s\",\n"
" clientId: \"%s\",\n"
" nonce: \"%s\",\n"
" },\n"
" ],\n"
" },\n"
" });\n"
" const { token } = identityCredential;\n"
" var input = document.getElementById('token');\n"
" input.value = token;\n"
" document.forms[0].submit();\n"
" }\n"
"</script>\n";

// TODO: get the configURL from the provider metadata/config somehow
const char *html_head = apr_psprintf(r->pool, java_script, "https://accounts.google.com/gsi/fedcm.json",
oidc_cfg_provider_client_id_get(provider), nonce);

// mimic fragment post
const char *html_body = apr_psprintf(r->pool,
" <p>Submitting...</p>\n"
" <form method=\"post\" action=\"%s\">\n"
" <p>\n"
" <input type=\"hidden\" id=\"token\" name=\"id_token"
"\" value=\"\">\n"
" <input type=\"hidden\" name=\"state"
"\" value=\"%s\">\n"
" <input type=\"hidden\" name=\"" OIDC_PROTO_RESPONSE_MODE
"\" value=\"" OIDC_PROTO_RESPONSE_MODE_FRAGMENT "\">\n"
" </p>\n"
" </form>\n",
redirect_uri, state);

return oidc_util_html_send(r, "FedCM", html_head, "signIn", html_body, OK);
};
4 changes: 4 additions & 0 deletions src/handle/handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ int oidc_discovery_request(request_rec *r, oidc_cfg_t *cfg);
apr_byte_t oidc_is_discovery_response(request_rec *r, oidc_cfg_t *cfg);
int oidc_discovery_response(request_rec *r, oidc_cfg_t *c);

// fedcm.c
int oidc_fedcm_request(request_rec *r, struct oidc_provider_t *provider, const char *redirect_uri, const char *state,
const char *nonce);

// info.c
int oidc_info_request(request_rec *r, oidc_cfg_t *c, oidc_session_t *session, apr_byte_t needs_save);

Expand Down
4 changes: 4 additions & 0 deletions src/proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ int oidc_proto_authorization_request(request_rec *r, struct oidc_provider_t *pro
rv = OK;
}

} else if (oidc_cfg_provider_auth_request_method_get(provider) == OIDC_AUTH_REQUEST_METHOD_FEDCM) {

rv = oidc_fedcm_request(r, provider, redirect_uri, state, nonce);

} else {
oidc_error(r, "oidc_cfg_provider_auth_request_method_get(provider) set to an unknown value: %d",
oidc_cfg_provider_auth_request_method_get(provider));
Expand Down

0 comments on commit 4be242a

Please sign in to comment.