/** * License: Public domain. * * Description: This snippet integrates the OIDC connect button with WooCommerce * to allow importing the customer's shopping details via OIDC. * Author Christian Grothoff */ // Add OIDC login form to checkout page. add_action( 'openid-connect-generic-register-login-form', function ( $login_form ) { // If WooCommerce is inactive, do nothing. if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true ) ) { return; } // Show login form at the shopping cart (if not logged in). add_action( 'woocommerce_before_checkout_billing_form', function ( $checkout ) use ( $login_form ) { $user = wp_get_current_user(); if ( 0 === $user->ID ) { // ID 0 is used to indicate user is not logged in. // Re-use filter logic to generate login page. print ( $login_form->handle_login_page( '' ) ); } } ); // Add action to set cookie to redirect back to current // (checkout) page after OIDC provided the data. add_action( 'woocommerce_before_checkout_billing_form', function ( $checkout ) use ( $login_form ) { $login_form->handle_redirect_cookie ( ); } ); } ); // Hook to convert OIDC fields to WC checkout fields if logged in. add_filter( 'woocommerce_checkout_fields', 'filter_checkout_get_value' ); /** * Checks if $claimname is in the body or _claim_names of the userinfo. * If yes, returns the claim value. Otherwise, returns false. * * @param string $claimname the claim name to look for * @param array $userinfo the JSON to look in * @param string $claimvalue the source claim value ( from the body of the JWT of the claim source) * @return True if a reference was found */ function get_claim( $claimname, $userinfo, &$claimvalue ) { if ( ! isset( $userinfo ) ) { return False; } /** * If we find a simple claim, return it. */ if ( array_keys_exists( $claimname, $userinfo ) ) { $claimvalue = $userinfo[$claimname]; return True; } /** * If there are not aggregated claims, it is over. */ if ( ! array_key_exists( '_claim_names', $userinfo ) || ! array_key_exists( '_claim_sources', $userinfo ) ) { return False; } $claim_src_ptr = $userinfo['_claim_names']; if ( ! isset( $claim_src_ptr ) ) { return False; } /** * No reference found */ if ( ! array_key_exists( $claimname, $claim_src_ptr ) ) { return False; } $src = $claim_src_ptr[$claimname]; //Reference found, but no corresponding JWT. This is a malformed userinfo if ( ! array_key_exists( $src, $userinfo['_claim_sources']) ) { return False; } //Source claim is not a JWT. Abort. if ( ! array_key_exists( 'JWT', $src ) ) { return False; } /** * Extract claim from JWT. * FIXME: We probably want to verify the JWT signature/issuer here! */ $jwt = $src['JWT']; list ($header, $body, $rest) = split('.', $jwt, 3); $body_decoded = base64_decode ( $body, false ); if ( ( isset ( $body_decoded ) ) && ( array_key_exists( $claimname, $body_decoded ) ) ) { $claimvalue = $body_decoded[$claimname]; return True; } return False; } /** * Filter to transform (defaults) for the Billing details according to * the information obtained from OpenID Connect (OIDC). WooCommerce * already grabs many of the values properly, but there are some fields * which we have to convert manually. * * @param array $in Data structure with shipping details to extend and return. * * @return array Enhanced shipping details. */ function filter_checkout_get_value( $in = array() ) { $user = wp_get_current_user(); if ( 0 !== $user->ID ) { $token_response = $user->get( 'openid-connect-generic-last-user-claim' ); $src = ''; if ( get_claim( 'given_name', $token_response, $given_name ) ) { $in['billing']['billing_first_name']['default'] = $given_name; $in['shipping']['shipping_first_name']['default'] = $given_name; } if ( get_claim( 'family_name', $token_response, $family_name ) ) { $in['billing']['billing_last_name']['default'] = $family_name; $in['shipping']['shipping_last_name']['default'] = $family_name; } if ( get_claim( 'phone_number', $token_response, $phone_number ) ) { $in['billing']['billing_phone']['default'] = $phone_number; $in['shipping']['shipping_phone']['default'] = $phone_number; } if ( get_claim( 'address', $token_response, $address ) ) { if ( array_key_exists( 'postal_code', $address ) ) { $postal_code = $address ['postal_code']; $in['billing']['billing_postcode']['default'] = $postal_code; $in['shipping']['shipping_postcode']['default'] = $postal_code; } if ( array_key_exists( 'country', $address ) ) { $country = $address ['country']; $in['billing']['billing_country']['default'] = $country; $in['shipping']['shipping_country']['default'] = $country; } if ( array_key_exists( 'locality', $address ) ) { $locality = $address ['locality']; $in['billing']['billing_city']['default'] = $locality; $in['shipping']['shipping_city']['default'] = $locality; } if ( array_key_exists( 'region', $address ) ) { $region = $address ['region']; $in['billing']['billing_state']['default'] = $region; $in['shipping']['shipping_state']['default'] = $region; } if ( array_key_exists( 'formatted', $address ) ) { $formatted = $address ['formatted']; $lines = explode( '\r\n', $formatted ); if ( count( $lines ) > 0 ) { $in['billing']['billing_address_1']['default'] = $lines[0]; $in['shipping']['shipping_address_1']['default'] = $lines[0]; } if ( count( $lines ) > 1 ) { $in['billing']['billing_address_2']['default'] = $lines[1]; $in['shipping']['shipping_address_2']['default'] = $lines[1]; } } if ( array_key_exists( 'street_address', $address ) ) { $street_address = $address ['street_address']; if ( ! array_key_exists( 'formatted', $address ) ) { $in['billing']['billing_address_1']['default'] = $street_address; $in['shipping']['shipping_address_1']['default'] = $street_address; } } } } return $in; }