dev/core#2141 - Add "local-redir" stub for use as OAuth2 "Redirect URL"
authorTim Otten <totten@civicrm.org>
Thu, 29 Oct 2020 01:47:42 +0000 (18:47 -0700)
committerTim Otten <totten@civicrm.org>
Tue, 3 Nov 2020 12:32:48 +0000 (04:32 -0800)
If you are developing on a local HTTP system with virtual hosts, then many
OAuth2 services won't recognize it as a local/dev URL.

The "local-redir.sh" script runs a stub service that will be accepted as
a local/dev "Redirect URL".

ext/oauth-client/bin/local-redir.php [new file with mode: 0644]
ext/oauth-client/bin/local-redir.sh [new file with mode: 0755]

diff --git a/ext/oauth-client/bin/local-redir.php b/ext/oauth-client/bin/local-redir.php
new file mode 100644 (file)
index 0000000..ab1bca9
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+
+if (PHP_SAPI !== 'cli-server') {
+  throw new \Exception(sprintf("Cannot redirect. The script %s must be launched PHP standalone mode (ex: %s).",
+    basename(__FILE__), 'DEST=http://example.com/ php -S localhost:3000'));
+}
+
+function buildInputUrl($s) {
+  $ssl = !empty($s['HTTPS']) && strtolower($s['HTTPS']) != 'off';
+  $url = ($ssl ? 'https' : 'http') . '://' . $s['HTTP_HOST'] . $s['REQUEST_URI'];
+  return $url;
+}
+
+function buildRedirectUrl($get) {
+  $url = getenv('DEST');
+  if (empty($url)) {
+    throw new \Exception(sprintf("Cannot redirect. The script %s requires environment variable %s.",
+      basename(__FILE__), 'DEST'));
+  }
+  $query = http_build_query($get);
+  $delim = strpos($url, '?') === FALSE ? '?' : '&';
+  return $url . ($query === '' ? '' : $delim . $query);
+}
+
+$inputUrl = buildInputUrl($_SERVER);
+$redirectUrl = buildRedirectUrl($_GET);
+error_log(sprintf("Redirect:\n  from: %s\n  to: %s\n", $inputUrl, $redirectUrl));
+header('Location: ' . $redirectUrl);
diff --git a/ext/oauth-client/bin/local-redir.sh b/ext/oauth-client/bin/local-redir.sh
new file mode 100755 (executable)
index 0000000..9ed55fb
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/bash
+set -e
+
+## Most OAuth2 providers allow you to register local dev sites if the "Redirect URL"
+## looks like "http://localhost:NNNN" or "http://127.0.0.1:NNNN".
+##
+## It is common in the CiviCRM community to develop on local virtual-hosts like "http://example.local".
+## These URLs cannot be directly registered with most OAuth2 providers.
+##
+## To resolve this either (1) enable HTTPS locally or (2) setup an intermediate redirect, e.g.
+##
+##   http://localhost:3000/my-return ==> http://example.local/civicrm/oauth/return
+##   https://public.example.com/my-return ==> http://example.local/civicrm/oauth/return
+##
+## The script "local-redir.sh" can help you setup an intermediate redirect. It will:
+##
+## 1. Launch a temporary HTTP service on "http://localhost:3000".
+## 2. Configure CiviCRM to work with "http://localhost:3000".
+##
+################################################################################
+
+## usage:      local-redir.sh [ip-or-host[:port]]
+##
+## example#1:  local-redir.sh
+## example#2:  local-redir.sh 127.0.0.1
+## example#3:  local-redir.sh localhost:8000
+
+###############################################################################
+## Bootstrap
+
+## Determine the absolute path of the directory with the file
+## usage: absdirname <file-path>
+function absdirname() {
+  pushd $(dirname $0) >> /dev/null
+    pwd
+  popd >> /dev/null
+}
+
+BINDIR=$(absdirname "$0")
+REDIRPHP="$BINDIR/local-redir.php"
+
+###############################################################################
+## Main
+
+BIND=${1:-localhost:3000}
+DEST=$(cv url -I civicrm/oauth-client/return)
+
+echo "local-redir.sh: Setup redirect proxy"
+echo
+echo "Intermediate URL: http://$BIND"
+echo "Canonical URL:    $DEST"
+echo
+echo "Update CiviCRM settings:"
+cv api setting.create oauthClientRedirectUrl="http://$BIND"
+
+export DEST
+php -S "$BIND" "$REDIRPHP"
+
+echo "Shutting down"
+echo
+echo "Reverting CiviCRM settings: oauthClientRedirectUrl"
+cv ev 'Civi::settings()->revert("oauthClientRedirectUrl");'