{"record":{"id":"3cbfbd7624fa5223","repo":"apereo/cas","slug":"unable-to-authenticate-request-to-register-service","errorCode":null,"errorMessage":"Unable to authenticate request to register service ${service.name}","messagePattern":"Unable to authenticate request to register service (.+?)","errorType":"exception","errorClass":"AuthenticationException","httpStatus":401,"severity":"error","filePath":"support/cas-server-support-rest-services/src/main/java/org/apereo/cas/support/rest/RegisteredServiceResource.java","lineNumber":86,"sourceCode":"     * @return {@link ResponseEntity} representing RESTful response\n     */\n    @PostMapping(value = \"/v1/services\", consumes = MediaType.APPLICATION_JSON_VALUE)\n    @Operation(summary = \"Create registered service\",\n        requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(\n            required = true,\n            description = \"Registered service JSON payload\",\n            content = @Content(\n                mediaType = MediaType.APPLICATION_JSON_VALUE,\n                schema = @Schema(implementation = RegisteredService.class)\n            )\n        ))\n    public ResponseEntity<String> createService(@RequestBody final RegisteredService service,\n                                                final HttpServletRequest request,\n                                                final HttpServletResponse response) {\n        try {\n            val auth = authenticateRequest(request);\n            if (auth == null) {\n                throw new AuthenticationException(\"Unable to authenticate request to register service \" + service.getName());\n            }\n            if (isAuthenticatedPrincipalAuthorized(auth)) {\n                this.servicesManager.save(service);\n                return new ResponseEntity<>(HttpStatus.OK);\n            }\n            return new ResponseEntity<>(\"Request is not authorized\", HttpStatus.FORBIDDEN);\n        } catch (final AuthenticationException e) {\n            return new ResponseEntity<>(StringEscapeUtils.escapeHtml4(e.getMessage()), HttpStatus.UNAUTHORIZED);\n        } catch (final Exception e) {\n            LoggingUtils.error(LOGGER, e);\n            return new ResponseEntity<>(StringEscapeUtils.escapeHtml4(e.getMessage()), HttpStatus.BAD_REQUEST);\n        }\n    }\n\n    private boolean isAuthenticatedPrincipalAuthorized(final Authentication auth) {\n        val attributes = auth.getPrincipal().getAttributes();\n        LOGGER.debug(\"Evaluating principal attributes [{}]\", attributes.keySet());\n        if (StringUtils.isBlank(this.attributeName) || StringUtils.isBlank(this.attributeValue)) {","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-rest-services/src/main/java/org/apereo/cas/support/rest/RegisteredServiceResource.java#L68-L104","documentation":"RegisteredServiceResource.createService throws AuthenticationException when authenticateRequest(request) returns null, i.e. the management REST call to register a service carried no recognizable authentication (typically missing/invalid HTTP Basic credentials). The endpoint refuses to save the service without an authenticated, authorized caller.","triggerScenarios":"POST to /cas/v1/services without an Authorization header; Basic auth header malformed or Base64 mis-encoded; credentials rejected so the underlying authentication result is null; the endpoint's basic-auth/ECP credential extraction path silently fails.","commonSituations":"Admin automation scripts omit the -u user:password option; wrong REST admin username/password after a config change; reverse proxy strips the Authorization header; CAS REST services authentication configuration (cas.authn.rest or management security settings) points at an unavailable auth source.","solutions":["Send HTTP Basic Authorization credentials with the request: curl -u admin:password -X POST .../v1/services.","Verify the credentials are valid against the configured REST/basic-auth authentication source.","Ensure no proxy or client library strips or rewrites the Authorization header.","Check the RegisteredServiceResource authentication configuration (service factory, authenticationSystemSupport beans) is present in the deployed overlay."],"exampleFix":"// before\ncurl -X POST 'https://cas/v1/services' -H 'Content-Type: application/json' -d '{...}'\n// after\ncurl -u casadmin:secret -X POST 'https://cas/v1/services' -H 'Content-Type: application/json' -d '{...}'","handlingStrategy":"validation","validationCode":"// Pre-flight: ensure an Authorization header is present before calling the endpoint\nif (authHeader == null || !authHeader.startsWith(\"Basic \")) {\n    throw new IllegalArgumentException(\"Service registration requires HTTP Basic Authorization header\");\n}","typeGuard":null,"tryCatchPattern":"try { registerService(service, adminUser, adminPass); }\ncatch (AuthenticationException e) {\n    logger.error(\"REST management auth failed; check credentials/config: \" + e.getMessage());\n    throw new IllegalStateException(\"Service registration requires valid admin credentials\", e);\n}","preventionTips":["Always send -u user:password (Basic auth) for /v1/services management calls.","Verify the Authorization header survives proxies and client libraries.","Keep management credentials in sync with the configured authentication source.","Test the credential against the auth source independently before automation runs."],"tags":["rest","cas","authentication","service-management"],"backgroundTag":"authentication-required","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}