Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help with OIDC Azure AD configuration/debugging #1434

Open
danieladarve opened this issue Aug 25, 2023 · 11 comments
Open

Help with OIDC Azure AD configuration/debugging #1434

danieladarve opened this issue Aug 25, 2023 · 11 comments

Comments

@danieladarve
Copy link

danieladarve commented Aug 25, 2023

Hello everyone,

I am running a dpkg install of Ansible Semaphore v2.8.92 in ubuntu 22.04 behind a nginx reverse proxy configured as suggested in the security section

I am able to click on the SSO button, login into microsoft but when the user is redirected back to the oidc return url, nothing happens, the page just seems to reload and it removes all parameters from the URL... I have tested using a different return url and i can see the token being returned in the parameters.

https://ansible-semaphore.test/api/auth/oidc/provider-name/redirect/?code=XXXXX&state=XXXXX&session_state=XXXXX

Here is what my oidc_providers config looks like:

"oidc_providers": {
		"provider-name": {
			"display_name": "Sign in with Provider",
			"provider_url": "https://login.microsoftonline.com/XXXXX/v2.0",
			"client_id": "XXXXX",
			"client_secret": "XXXXX",
			"scopes": ["openid", "profile", "email"],
			"username_claim": "preferred_username",
			"name_claim": "preferred_username",
			"email_claim": "email"
		}
	}

I can see the correct scopes, and claims
Here is what my /v2.0/.well-known/openid-configuration looks like:

{
  "token_endpoint": "https://login.microsoftonline.com/xxxxx/oauth2/v2.0/token",
  "token_endpoint_auth_methods_supported": [
    "client_secret_post",
    "private_key_jwt",
    "client_secret_basic"
  ],
  "jwks_uri": "https://login.microsoftonline.com/xxxxx/discovery/v2.0/keys",
  "response_modes_supported": [
    "query",
    "fragment",
    "form_post"
  ],
  "subject_types_supported": [
    "pairwise"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "response_types_supported": [
    "code",
    "id_token",
    "code id_token",
    "id_token token"
  ],
  "scopes_supported": [
    "openid",
    "profile",
    "email",
    "offline_access"
  ],
  "issuer": "https://login.microsoftonline.com/xxxxx/v2.0",
  "request_uri_parameter_supported": false,
  "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo",
  "authorization_endpoint": "https://login.microsoftonline.com/xxxxx/oauth2/v2.0/authorize",
  "device_authorization_endpoint": "https://login.microsoftonline.com/xxxxx/oauth2/v2.0/devicecode",
  "http_logout_supported": true,
  "frontchannel_logout_supported": true,
  "end_session_endpoint": "https://login.microsoftonline.com/xxxxx/oauth2/v2.0/logout",
  "claims_supported": [
    "sub",
    "iss",
    "cloud_instance_name",
    "cloud_instance_host_name",
    "cloud_graph_host_name",
    "msgraph_host",
    "aud",
    "exp",
    "iat",
    "auth_time",
    "acr",
    "nonce",
    "preferred_username",
    "name",
    "tid",
    "ver",
    "at_hash",
    "c_hash",
    "email"
  ],
  "kerberos_endpoint": "https://login.microsoftonline.com/xxxxx/kerberos",
  "tenant_region_scope": "OC",
  "cloud_instance_name": "microsoftonline.com",
  "cloud_graph_host_name": "graph.windows.net",
  "msgraph_host": "graph.microsoft.com",
  "rbac_url": "https://pas.windows.net"
}

Ansible Semaphore Config

{
 	"mysql": {
 		"host": "127.0.0.1:3306",
 		"user": "XXXXX",
 		"pass": "XXXXX",
 		"name": "ansible",
 		"options": null
 	},
 	"bolt": {
 		"host": "",
 		"user": "",
 		"pass": "",
 		"name": "",
 		"options": null
 	},
 	"postgres": {
 		"host": "",
 		"user": "",
 		"pass": "",
 		"name": "",
 		"options": null
 	},
 	"dialect": "mysql",
 	"port": "",
 	"interface": "",
 	"tmp_path": "/tmp/semaphore",
 	"cookie_hash": "XXXXX",
 	"cookie_encryption": "XXXXX",
 	"access_key_encryption": "XXXXX",
 	"email_sender": "",
 	"email_host": "",
 	"email_port": "",
 	"email_username": "",
 	"email_password": "",
 	"web_host": "",
 	"ldap_binddn": "",
 	"ldap_bindpassword": "",
 	"ldap_server": "",
 	"ldap_searchdn": "",
 	"ldap_searchfilter": "",
 	"ldap_mappings": {
 		"dn": "",
 		"mail": "",
 		"uid": "",
 		"cn": ""
 	},
 	"telegram_chat": "",
 	"telegram_token": "",
 	"slack_url": "",
 	"max_parallel_tasks": 0,
 	"email_alert": false,
 	"email_secure": false,
 	"telegram_alert": false,
 	"slack_alert": false,
 	"ldap_enable": false,
 	"ldap_needtls": false,
 	"ssh_config_path": "",
 	"demo_mode": false,
 	"git_client": "",
	"password_login_disable": true,
	"oidc_providers": {
		"snooze": {
			"display_name": "Sign in with Provider",
			"provider_url": "https://login.microsoftonline.com/XXXXX/v2.0",
			"client_id": "XXXXX",
			"client_secret": "XXXXX",
			"scopes": ["openid", "profile", "email"],
			"username_claim": "preferred_username",
			"name_claim": "preferred_username",
			"email_claim": "email"
		}
	}
}

Nginx Configuration

upstream semaphore {
	server 127.0.0.1:3000;
}

server {
	client_max_body_size 0;
	chunked_transfer_encoding on;
	
	server_name subdomain.website.com;

	location / {
		proxy_pass http://semaphore/;
		proxy_set_header Host $http_host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_buffering off;
		proxy_request_buffering off;
	}

	location /api/ws {
		proxy_pass http://semaphore/api/ws;
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
		proxy_set_header Origin "";
	}

    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/subdomain.website.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/subdomain.website.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}


server {
    if ($host = subdomain.website.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


	listen 80 default_server;
	listen [::]:80 default_server;

	server_name subdomain.website.com;
    return 404; # managed by Certbot


}

In the Azure side I have tested with both

  1. ID tokens (used for implicit and hybrid flows)
  2. Access tokens (used for implicit flows)

I was wondering if anyone has had success configuring Azure AD and could point me in the right direction. Additionally, I'd like to understand if there's a way for me to debug what happens after the user is redirected and lands back on the Semaphore redirect URL.

Thank you!

@bilalbayasut
Copy link

bilalbayasut commented Oct 2, 2023

faced exactly same issue with you @danieladarve , any updates regarding this ? , can you check in your ends the logs

sudo cat /var/log/syslog | grep semaphore

I've checked mine, but I got

level=error msg="404 Not Found: "

which is strange, eventhough my semaphore run behind port-forwarding, should be no issue re that

@ocient-jlarson
Copy link

Very similar issue but with Okta.

@Loigzorn
Copy link

level=error msg="404 Not Found: "

Facing a similar issue with Authentik.

@xfact-joseph-p
Copy link

xfact-joseph-p commented Nov 27, 2023

I was encountering similar issues but I now have a working configuration.

  • OS: Ubuntu 22.04
  • Semaphore Version: 2.9.37

config.json includes the following:

          "oidc_providers": {
                "azure": {
                        "color": "blue",
                        "display_name": "Sign in with Azure (Entra ID)",
                        "provider_url": "https://login.microsoftonline.com/<Tennant ID>/v2.0",
                        "client_id": "<ID>",
                        "client_secret": "<secret>",
                        "redirect_url": "https://semaphore.test.com/api/auth/oidc/azure/redirect"
                }
        },

Note of course that the redirect_uri should match what is set in AzureAD as a valid (Web) redirect uri: https://semaphore.test.com/api/auth/oidc/azure/redirect

My instance is behind an Nginx reverse proxy, but that config is pretty vanilla like in this documentation here: https://docs.ansible-semaphore.com/administration-guide/security

But for the record, my Nginx configuration for this site is is like:

upstream semaphore {
    server 127.0.0.1:3000;
  }

server {
    listen 80;
    server_name semaphore.test.com;
    return 301 https://semaphore.test.com$request_uri;
}



server {
        listen 443 ssl;
        ssl_certificate /etc/ssl/server.test.semaphore.pem;
        ssl_certificate_key /etc/ssl/server.test.semaphore.pem;
        server_name semaphore.test.com;
        client_max_body_size 0;
        chunked_transfer_encoding on;

    location / {
      proxy_pass http://semaphore/;
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_buffering off;
      proxy_request_buffering off;
    }

    location /api/ws {
      proxy_pass http://semaphore/api/ws;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Origin "";
    }
}

@RyanGelinas
Copy link

This example worked for me, so I created a PR in the docs repo to add it there. Thanks @xfact-joseph-p !

@tboerger
Copy link
Collaborator

tboerger commented Jun 6, 2024

There is also a config including all scopes at #2031 (comment) which should be added to the docs.

@m-soltani
Copy link

I am having the same issue and have configured my oidc provider as in #2031. I get the following error:


time="2024-06-29T17:42:32Z" level=error msg="oauth2: \"invalid_grant\" \"AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token. Trace ID: 9156e6e8-c9eb-4829-a926-b0d0d6c69a00 Correlation ID: f2714ddd-d611-4023-8044-32499e98c6fb Timestamp: 2024-06-29 17:42:32Z\""

Is it really the case that semaphore server uses duplicate authorization codes?

I am running the docker-compose sample setup from the repository.

@m-soltani
Copy link

m-soltani commented Jun 29, 2024

I am having the same issue and have configured my oidc provider as in #2031. I get the following error:


time="2024-06-29T17:42:32Z" level=error msg="oauth2: \"invalid_grant\" \"AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token. Trace ID: 9156e6e8-c9eb-4829-a926-b0d0d6c69a00 Correlation ID: f2714ddd-d611-4023-8044-32499e98c6fb Timestamp: 2024-06-29 17:42:32Z\""

Is it really the case that semaphore server uses duplicate authorization codes?

I am running the docker-compose sample setup from the repository.

It turns out , you need cookie_hash and cookie_encryption properties to be set in order for authentication flow to work correctly. This is not a documented behavior and it was not clear how to generate those keys. I did find a sample in another GitHub issue and use that as baseline. If I could contribute to the documentation, that would be really good - Is this allowed?

@fiftin
Copy link
Collaborator

fiftin commented Jul 21, 2024

Hi @m-soltani https://docs.semaphoreui.com/administration-guide/security

@MatthewHana
Copy link

Hello @danieladarve, could you please see if the workaround in issue #2681 solves your issue.

@m-soltani
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants