Closed ansidorov closed 4 years ago
IIRC the IdP needs to send the code in the url when redirecting back to DD. This is step5 and it's already missing there. Might be better to ask in python-social-auth as all this is handled in that library.
Or to speed it up to use SAML against to KEYCLOAK it work out of the box.
Or to speed it up to use SAML against to KEYCLOAK it work out of the box.
Do you have a working example?
I set it up this way:
DD_SAML2_ENABLED: 'True'.
DD_SAML2_ENTITY_ID: "defectdojo-dev"
DD_SAML2_METADATA_AUTO_CONF_URL: "https://example.com/auth/realms/example/protocol/saml/descriptor"
But I get an error invalid redirect_uri
.
DefectDojo logs:
uwsgi_1 | GET to https://example.com/auth/realms/example/protocol/saml/descriptor
uwsgi_1 | Starting new HTTPS connection (1): example.com:443
uwsgi_1 | https://example.com:443 "GET /auth/realms/example/protocol/saml/descriptor HTTP/1.1" 200 None
uwsgi_1 | Response status: 200
uwsgi_1 | example.com: 'Set-Cookie: INGRESS_SESSION_ID=1604051893.223.1076.820077; HttpOnly; Path=/auth/realms/example/; Secure'
uwsgi_1 | service(https://example.com/auth/realms/example, idpsso_descriptor, single_sign_on_service, urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect)
uwsgi_1 | service => [{'__class__': 'urn:oasis:names:tc:SAML:2.0:metadata&SingleSignOnService', 'binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', 'location': 'https://iexample.com/auth/realms/example/protocol/saml'}]
uwsgi_1 | destination to provider: https://example.com/auth/realms/example/protocol/saml
uwsgi_1 | REQUEST: <ns0:AuthnRequest xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:ns1="urn:oasis:names:tc:SAML:2.0:assertion" AssertionConsumerServiceURL="/saml2/acs/" Destination="https://example.com/auth/realms/example/protocol/saml" ID="id-IRJ0z0yH6JZM0NiZp" IssueInstant="2020-10-30T09:58:12Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><ns1:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">defectdojo-dev</ns1:Issuer></ns0:AuthnRequest>
uwsgi_1 | AuthNReq: <ns0:AuthnRequest xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:ns1="urn:oasis:names:tc:SAML:2.0:assertion" AssertionConsumerServiceURL="/saml2/acs/" Destination="https://example.com/auth/realms/example/protocol/saml" ID="id-IRJ0z0yH6JZM0NiZp" IssueInstant="2020-10-30T09:58:12Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><ns1:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">defectdojo-dev</ns1:Issuer></ns0:AuthnRequest>
uwsgi_1 | HTTP REDIRECT
uwsgi_1 | [pid: 22|app: 0|req: 4/4] 192.168.37.2 () {44 vars in 916 bytes} [Fri Oct 30 09:58:11 2020] GET /saml2/login/ => generated 0 bytes in 542 msecs (HTTP/1.1 302) 8 headers in 854 bytes (1 switches on core 1)
nginx_1 | 192.168.37.2 - - [30/Oct/2020:09:58:12 +0000] "GET /saml2/login/ HTTP/1.1" 302 0 "http://defectdojo.dc:8080/login?next=/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" "-"
Client in Keycloak:
DD_SAML2_ENABLED: 'true'
DD_SAML2_METADATA_AUTO_CONF_URL: 'http://idp_FQDN/auth/realms/master/protocol/saml/descriptor'
DD_SAML2_ENTITY_ID: 'https://defect-dojourl/saml2_auth/acs/' # need to be mapped to IDP
DD_SAML2_ASSERTION_URL: 'https://DD_FQDN'
DD_SAML2_ATTRIBUTE_MAPS_EMAIL: 'email'
DD_SAML2_ATTRIBUTE_MAPS_USERNAME: 'User.Username'
DD_SAML2_ATTRIBUTE_MAPS_FIRSTNAME: 'first_name'
DD_SAML2_ATTRIBUTE_MAPS_LASTNAME: 'last_name'
If you don't know what to map use SAMLTracer
AFAIK SLO is implemented as well, but I have to test it first.
I hope this helps
@dsever Thank you very much, everything worked out perfectly.
Bug description After adding a patch to support Keycloak SSO, if the login is successful, I receive an Authentication process error canceled.
Steps to reproduce Steps to reproduce the behavior:
+KEYCLOAK_OAUTH2_ENABLED = env('DD_SOCIAL_AUTH_KEYCLOAK_OAUTH2_ENABLED') +SOCIAL_AUTH_KEYCLOAK_KEY = env('DD_SOCIAL_AUTH_KEYCLOAK_KEY') +SOCIAL_AUTH_KEYCLOAK_SECRET = env('DD_SOCIAL_AUTH_KEYCLOAK_SECRET') +SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY = env('DD_SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY') +SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = env('DD_SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL') +SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = env('DD_SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL') +SOCIAL_AUTH_KEYCLOAK_ID_KEY = env('DD_SOCIAL_AUTH_KEYCLOAK_ID_KEY') + AUTH0_OAUTH2_ENABLED = env('DD_SOCIAL_AUTH_AUTH0_OAUTH2_ENABLED') SOCIAL_AUTH_AUTH0_KEY = env('DD_SOCIAL_AUTH_AUTH0_KEY') SOCIAL_AUTH_AUTH0_SECRET = env('DD_SOCIAL_AUTH_AUTH0_SECRET') @@ -422,6 +438,7 @@ LOGIN_EXEMPT_URLS = ( r'^%sfinding/image/(?P[^/]+)$' % URL_PREFIX,
r'^%sapi/v2/' % URL_PREFIX,
r'complete/',
r'complete/keycloak/', r'saml2/login', r'saml2/acs', r'empty_questionnaire/([\d]+)/answer' diff --git a/dojo/templates/dojo/login.html b/dojo/templates/dojo/login.html index dc4a777..3f68223 100644 --- a/dojo/templates/dojo/login.html +++ b/dojo/templates/dojo/login.html @@ -55,6 +55,14 @@
{% if KEYCLOAK_ENABLED is True %}
Login with Keycloak
{% endif %}
curl -X POST -d "client_id=defectdojo-dev" -d "client_secret=3f7d1f05f-f1f4-48713-8bd0-d12z2eebbdadd" -d "code=''" -d "grant_type=authorization_code" -d "redirect_uri=http://defectdojo.dc:8080/complete/keycloak/\?redirect_state\=RfDaN1Wbzs2WIdP5f5aPU3VTUb6Ijk0l" -H 'Accept: application/json' -H 'Content-Type: application/x-www-form-urlencoded' https://example.com/auth/realms/example/protocol/openid-connect/token -i HTTP/2 400 date: Fri, 30 Oct 2020 08:45:21 GMT content-type: application/json content-length: 62 set-cookie: INGRESS_SESSION_ID=1604047522.535.1076.949539; Path=/auth/realms/example/; Secure; HttpOnly cache-control: no-store pragma: no-cache strict-transport-security: max-age=15724800; includeSubDomains
{"error":"invalid_grant","error_description":"Code not valid"}%
uwsgi_1 | Starting new HTTPS connection (1): example.com:443 uwsgi_1 | https://example.com:443 "POST /auth/realms/example/protocol/openid-connect/token HTTP/1.1" 400 62 uwsgi_1 | Internal Server Error: /complete/keycloak/ nginx_1 | 192.168.37.2 - - [30/Oct/2020:08:59:39 +0000] "GET /complete/keycloak/?redirect_state=iMQD3TUft1WiQJJWKUWihgJZ94jlTN6m&session_state=c39bd808-ecb5-45b5-b179-166ff535f8ce HTTP/1.1" 500 143323 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36" "-" uwsgi_1 | Traceback (most recent call last): uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/utils.py", line 251, in wrapper uwsgi_1 | return func(*args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/oauth.py", line 401, in auth_complete uwsgi_1 | method=self.ACCESS_TOKEN_METHOD uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/oauth.py", line 373, in request_access_token uwsgi_1 | return self.get_json(*args, *kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/base.py", line 238, in get_json uwsgi_1 | return self.request(url, args, kwargs).json() uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/base.py", line 234, in request uwsgi_1 | response.raise_for_status() uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/requests/models.py", line 941, in raise_for_status uwsgi_1 | raise HTTPError(http_error_msg, response=self) uwsgi_1 | requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://example.com/auth/realms/example/protocol/openid-connect/token uwsgi_1 | uwsgi_1 | During handling of the above exception, another exception occurred: uwsgi_1 | uwsgi_1 | Traceback (most recent call last): uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner uwsgi_1 | response = get_response(request) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response uwsgi_1 | response = self.process_exception_by_middleware(e, request) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response uwsgi_1 | response = wrapped_callback(request, *callback_args, callback_kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func uwsgi_1 | response = view_func(request, *args, *kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view uwsgi_1 | return view_func(args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_django/utils.py", line 49, in wrapper uwsgi_1 | return func(request, backend, *args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_django/views.py", line 33, in complete uwsgi_1 | *args, *kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/actions.py", line 45, in do_complete uwsgi_1 | user = backend.complete(user=user, args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/base.py", line 40, in complete uwsgi_1 | return self.auth_complete(*args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/utils.py", line 254, in wrapper uwsgi_1 | raise AuthCanceled(args[0], response=err.response) uwsgi_1 | social_core.exceptions.AuthCanceled: Authentication process canceled uwsgi_1 | Internal Server Error: /complete/keycloak/ uwsgi_1 | Traceback (most recent call last): uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/utils.py", line 251, in wrapper uwsgi_1 | return func(*args, *kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/oauth.py", line 401, in auth_complete uwsgi_1 | method=self.ACCESS_TOKEN_METHOD uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/oauth.py", line 373, in request_access_token uwsgi_1 | return self.get_json(args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/base.py", line 238, in get_json uwsgi_1 | return self.request(url, *args, kwargs).json() uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/base.py", line 234, in request uwsgi_1 | response.raise_for_status() uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/requests/models.py", line 941, in raise_for_status uwsgi_1 | raise HTTPError(http_error_msg, response=self) uwsgi_1 | requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://example.com/auth/realms/example/protocol/openid-connect/token uwsgi_1 | uwsgi_1 | During handling of the above exception, another exception occurred: uwsgi_1 | uwsgi_1 | Traceback (most recent call last): uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner uwsgi_1 | response = get_response(request) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response uwsgi_1 | response = self.process_exception_by_middleware(e, request) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response uwsgi_1 | response = wrapped_callback(request, *callback_args, *callback_kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func uwsgi_1 | response = view_func(request, args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view uwsgi_1 | return view_func(*args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_django/utils.py", line 49, in wrapper uwsgi_1 | return func(request, backend, *args, *kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_django/views.py", line 33, in complete uwsgi_1 | args, kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/actions.py", line 45, in do_complete uwsgi_1 | user = backend.complete(user=user, *args, *kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/backends/base.py", line 40, in complete uwsgi_1 | return self.auth_complete(args, **kwargs) uwsgi_1 | File "/usr/local/lib/python3.6/site-packages/social_core/utils.py", line 254, in wrapper uwsgi_1 | raise AuthCanceled(args[0], response=err.response) uwsgi_1 | social_core.exceptions.AuthCanceled: Authentication process canceled