Strange problem with CORS and redirections in frontend Vue.js + backend PHP

71 views
Skip to first unread message

Oscar Alonso

unread,
Sep 12, 2024, 8:37:59 AM9/12/24
to CAS Community

Hello,

 

I'm testing an app prototype that authenticates through CAS 7.0.6.

The architecture is as follows:

-Frontend in Vue, with a function that calls a backend API in order to authenticate.

  (for example, hostname would be frontend.mydomain).

  Source code for authenticating is as follows:

 

import axios from 'axios';

export default {
  async authenticate() {
    try {
      const response = await axios.get('https://backend.mydomain/api/authenticate.php', {
        withCredentials: true
      });
      return response.data;
    } catch (error) {
      console.error('Error during authentication:', error);
      return null;
    }

  }
};

 

-Backend in PHP, using phpCAS.

  (For example, hostname would be backend.mydomain).

  Source code is as follows:

 

<?php

header('Access-Control-Allow-Origin: https://frontend.mydomain);
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Content-Type: application/json');

require_once '../vendor/autoload.php';

// OPTIONS requests handling
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    exit;  // Just in case, not needed.
}

phpCAS::client(CAS_VERSION_2_0, 'cas-server.mydomain2', 443, '/cas', 'https://frontend.mydomain');
phpCAS::setNoCasServerValidation();

// Check if user is authenticated
if (phpCAS::isAuthenticated()) {
    $user = phpCAS::getUser();
    $attributes = phpCAS::getAttributes();

    // Returns user data in JSON format
    echo json_encode([
        'authenticated' => true,
        'user' => $user,
        'attributes' => $attributes

    ]);
} else {
    // Redirects user to CAS login page
    phpCAS::forceAuthentication();
}
?>

 

-CAS Server 7.0.6, with hostname cas-server.mydomain2.

Relevant CAS configuration:

 

/etc/cas/config/cas.properties (excerpt):

cas.http-web-request.cors.enabled=true
cas.http-web-request.header.enabled=true

cas.http-web-request.cors.allow-credentials=false

cas.http-web-request.cors.allow-origins=*

cas.http-web-request.cors.allow-methods=*
cas.http-web-request.cors.allow-headers=*
cas.http-web-request.cors.max-age=3600

 

I also tried cas.http-web-request.cors.allow-credentials=true and cas.http-web-request.cors.allow-origin-patterns=https://frontend.mydomain,https://cas-server.mydomain2   with no luck.

 

/etc/cas/services/frontend-9900018.json:

{
  "id" : 9900018,
  "name" : "Frontend",
  "description" : "Frontend",
  "serviceId" : "^https:\\/\\/frontend[.]mydomain(?:\\/?|\\/.*)",
  "@class" : "org.apereo.cas.services.CasRegisteredService",
  "evaluationOrder" : 10,
  "logoutType" : "BACK_CHANNEL",
  "logoutUrl" : "https://login.microsoftonline.com/xxxxx-redacted-for-obfuscation-xxxxx/saml2"
  "accessStrategy" : {
    "@class" : "org.apereo.cas.services.DefaultRegisteredServiceAccessStrategy",
    "delegatedAuthenticationPolicy" : {
      "@class" : "org.apereo.cas.services.DefaultRegisteredServiceDelegatedAuthenticationPolicy",
      "allowedProviders" : [ "java.util.ArrayList", [ "My-SAML-Provider" ] ],
      "exclusive": true
    }
  }
  "attributeReleasePolicy" : {
    "@class" : "org.apereo.cas.services.ReturnMappedAttributeReleasePolicy",
    "allowedAttributes" : {
      "@class" : "java.util.TreeMap",
      "userid" : "groovy { return attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name']}"
      "displayname" : "groovy { return attributes['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/displayname']}"
      "roles" : "groovy { return attributes['http://schemas.microsoft.com/ws/2008/06/identity/claims/role']}"
    }
  }

  "properties" : {
    "@class" : "java.util.HashMap",
    "corsAllowedOrigins" : {
      "@class" : "org.apereo.cas.services.DefaultRegisteredServiceProperty",
      "values" : [ "java.util.HashSet", [ "https://frontend.mydomain" ] ]
    }
    "corsAllowCredentials" : {
      "@class" : "org.apereo.cas.services.DefaultRegisteredServiceProperty",
      "values" : [ "java.util.HashSet", [ "true" ] ]
    }
  }
}

 

Of course, SAML configuration is right (verified in other services  with traditional PHP that renders pages).

 

When I go to URL https://frontend.mydomain in browser, I can see in dev tools the following error:

 

"Access to XMLHttpRequest at 'frontend.mydomain/:1 https://cas-server.mydomain2/cas/login?service=https%3A%2F%2Ffrontend.mydomain%2Fapi%2Fauthenticate.php' (redirected from 'https://backend.mydomain/api/authenticate.php') from origin 'https://frontend.mydomain' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present  on the requested resource."

 

"GET https://cas-server.mydomain2/cas/login?service=https%3A%2F%2Ffrontend.mydomain%2Fapi%2Fauthenticate.php net::ERR_FAILED 403 (Forbidden)

 

Looking at the request headers of the failing request, I can see "Origin: null" and I think this could be the culprit.

 

Why Axios/browser is sending the GET request to CAS server with "Origin: null" header?

 

Anybody tried this architecture an faced the same issues?

 

Thanks in advance.

 

Best regards,

Oscar Alonso

 

 

 

 

Pascal Rigaux

unread,
Sep 12, 2024, 10:09:03 AM9/12/24
to cas-...@apereo.org
Hi,

You can *not* do CAS protocol with XHR-CORS (you can't follow HTTP 302 and have CAS cookies)

You have to *redirect* to a page that does the login (or use JSONP).

This may help: https://prigaux.frama.io/cas-spa-docs/

cu

On 12/09/2024 13:54, 'Oscar Alonso' via CAS Community wrote:
> Hello,
>
> I'm testing an app prototype that authenticates through CAS 7.0.6.
>
> The architecture is as follows:
>
> -Frontend in Vue, with a function that calls a backend API in order to authenticate.
>
>   (for example, hostname would be frontend.mydomain).
>
>   Source code for authenticating is as follows:
>
> importaxios from 'axios';
>
> exportdefault{
> async authenticate() {
> try{
> const response = awaitaxios.get('https://backend.mydomain/api/authenticate.php', {
Reply all
Reply to author
Forward
0 new messages