Coder Social home page Coder Social logo

saml-auth-proxy's Introduction

Test

Provides a SAML SP authentication proxy for backend web services

Usage

  -allow-idp-initiated
        If set, allows for IdP initiated authentication flow (env SAML_PROXY_ALLOW_IDP_INITIATED)
  -attribute-header-mappings attribute=header
        Comma separated list of attribute=header pairs mapping SAML IdP response attributes to forwarded request header (env SAML_PROXY_ATTRIBUTE_HEADER_MAPPINGS)
  -attribute-header-wildcard string
        Maps all SAML attributes with this option as a prefix, slashes in attribute names will be replaced by dashes (env SAML_PROXY_ATTRIBUTE_HEADER_WILDCARD)
  -auth-verify bool
        Enables verify path endpoint for forward auth and trusts X-Forwarded headers (env SAML_PROXY_AUTH_VERIFY)
  -auth-verify-path string
        Path under BaseUrl that will respond with a 200 when authenticated (env SAML_PROXY_AUTH_VERIFY_PATH) (default "/_verify")
  -authorize-attribute attribute
        Enables authorization and specifies the attribute to check for authorized values (env SAML_PROXY_AUTHORIZE_ATTRIBUTE)
  -authorize-values values
        If enabled, comma separated list of values that must be present in the authorize attribute (env SAML_PROXY_AUTHORIZE_VALUES)
  -backend-url URL
        URL of the backend being proxied (env SAML_PROXY_BACKEND_URL)
  -base-url URL
        External URL of this proxy (env SAML_PROXY_BASE_URL)
  -bind host:port
        host:port to bind for serving HTTP (env SAML_PROXY_BIND) (default ":8080")
  -cookie-domain string
        Overrides the domain set on the session cookie. By default the BaseUrl host is used. (env SAML_PROXY_COOKIE_DOMAIN)
  -cookie-max-age duration
        Specifies the amount of time the authentication token will remain valid (env SAML_PROXY_COOKIE_MAX_AGE) (default 2h0m0s) 
  -cookie-name string
        Name of the cookie that tracks session token (env SAML_PROXY_COOKIE_NAME) (default "token")
  -entity-id string
        Entity ID of this service provider (env SAML_PROXY_ENTITY_ID)
  -idp-ca-path path
        Optional path to a CA certificate PEM file for the IdP (env SAML_PROXY_IDP_CA_PATH)
  -idp-metadata-url URL
        URL of the IdP's metadata XML, can be a local file by specifying the file:// scheme (env SAML_PROXY_IDP_METADATA_URL)
  -initiate-session-path path
        If set, initiates a SAML authentication flow only when a user visits this path. This will allow anonymous users to access to the backend. (env SAML_PROXY_INITIATE_SESSION_PATH)
  -name-id-format string
        One of unspecified, transient, email, or persistent to use a standard format or give a full URN of the name ID format (env SAML_PROXY_NAME_ID_FORMAT) (default "transient")
  -idp-metadata-url URL
        URL of the IdP's metadata XML, can be a local file by specifying the file:// scheme (env SAML_PROXY_IDP_METADATA_URL)
  -name-id-format string
        One of unspecified, transient, email, or persistent to use a standard format or give a full URN of the name ID format (env SAML_PROXY_NAME_ID_FORMAT) (default "transient")
  -name-id-mapping header
        Name of the request header to convey the SAML nameID/subject (env SAML_PROXY_NAME_ID_MAPPING)
  -new-auth-webhook-url URL
        URL of webhook that will get POST'ed when a new authentication is processed (env SAML_PROXY_NEW_AUTH_WEBHOOK_URL)
  -sp-cert-path path
        The path to the X509 public certificate PEM file for this SP (env SAML_PROXY_SP_CERT_PATH) (default "saml-auth-proxy.cert")
  -sp-key-path path
        The path to the X509 private key PEM file for this SP (env SAML_PROXY_SP_KEY_PATH) (default "saml-auth-proxy.key")
  -static-relay-state string
        A fixed RelayState value, such as a short URL. Will be trimmed to 80 characters to conform with SAML. The default generates random bytes that are Base64
 encoded. (env SAML_PROXY_STATIC_RELAY_STATE)
  -version
        show version and exit

The snake-case values, such as SAML_PROXY_BACKEND_URL, are the equivalent environment variables that can be set instead of passing configuration via the command-line.

The command-line argument usage renders with only a single leading dash, but GNU-style double-dashes can be used also, such as --sp-key-path.

Authorization

The proxy has support for not only authenticating users via a SAML IdP, but can also further authorize access by evaluating the attributes included in the SAML response assertion.

The authorization is configured with the combination of --authorize-attribute and --authorize-values.

NOTE the attribute is case sensitive, so be sure to specify that parameter exactly as it appears in the Name attribute of the <saml:Attribute> element.

The values are a comma separated list of authorized values and since the assertion attributes can contain more than one value also, the authorization performs an "intersection" matching any one of the expected values with any one of the assertion attribute values. That allows for matching user IDs where the assertion has a single value but you want to allow one or more users to be authorized. It also allows for matching group names where each user may be belong to more than one group and you may want to also authorize any number of groups.

The proxy also has support for Traefik forward auth and the caddy variant. The --auth-verify and --auth-verify-path parameters can be used to enable a verify endpoint that will respond with a 204 when the user is authenticated.

WARNING the --auth-verify option trusts the X-Forwarded-* headers and should only be used when the proxy is behind a gateway; one that clears and sets those headers.

Note for AJAX/Fetch Operations

If the web application being protected behind this proxy makes AJAX/Fetch calls, then be sure to enable "same-origin" access for the credentials of those calls, as described here.

With that configuration in place, the AJAX/Fetch calls will leverage the same token cookie provided in response to the first authenticated page retrieval via the proxy.

When the user is authorized, the proxied request header X-Authorized-Using will be populated with the attribute=value that was matched, such as

X-Authorized-Using: UserID=user1

Health Endpoint

The proxy itself provides a health endpoint at /_health that can be used to confirm the proxy is healthy/ready independent of the SAML processing. It returns a status code of 200 and a text/plain body with "OK".

Building

With Go 1.11 or newer:

go build

Trying it out

The following procedure will enable you to try out the proxy running locally and using Grafana as a backend to proxy with authentication. It will use SSOCircle as a SAML IdP.

Start the supplied Grafana and Web Debug Server using Docker Compose:

docker-compose up -d

Create a domain name that resolves to 127.0.0.1 and use that as the BASE_FQDN in the following operations;

Generate the SP certificate and key material by running:

# IMPORTANT: set this
BASE_FQDN=...
openssl req -x509 -newkey rsa:2048 -keyout saml-auth-proxy.key -out saml-auth-proxy.cert -days 365 -nodes -subj "/CN=${BASE_FQDN}"

Start saml-auth-proxy using:

./saml-auth-proxy \
  --base-url http://${BASE_FQDN}:8080 \
  --backend-url http://localhost:3000 \
  --idp-metadata-url=https://samltest.id/saml/idp \
  --attribute-header-mappings UserID=x-webauth-user

Generate your SP's SAML metadata by accessing the built-in metadata endpoint:

curl localhost:8080/saml/metadata > saml-sp-metadata.xml

or with PowerShell

Invoke-RestMethod -Uri http://localhost:8080/saml/metadata -OutFile .\saml-sp-metadata.xml

You can upload the file saml-sp-metadata.xml file at samltest.id.

Note you will also be selecting the attributes that will be included in the assertion in the SAML authentication response, such as:

  • FirstName
  • LastName
  • EmailAddress
  • UserID

To try out authorization you would add the following arguments referencing something like UserID and one or more expected SAMLTest user's values:

  --authorize-attribute UserID \
  --authorize-values user1,user2

Now you can open your browser and navigate to http://${BASE_FQDN}:8080. You will be redirected via SAMLTest's login page and then be returned with access to Grafana.

Force a logout from the IdP by going to https://samltest.id/idp/profile/Logout

Troubleshooting

ERROR: failed to decrypt response

If the SAML redirect results in a "Forbidden" white-page and the saml-auth-proxy outputs a log like the following, then be sure to double check that the subject/CN of the generated certificate matches the FQDN of the deployed endpoint.

ERROR: failed to decrypt response: crypto/rsa: decryption error

After correcting the certificate and key, be sure to regenerate the metadata and provide that to the ADFS/SAML IdP owner.

saml-auth-proxy's People

Contributors

aledegano avatar dependabot[bot] avatar graham-web avatar infamy avatar itzg avatar kennethklee avatar piffall avatar tinselspoon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

saml-auth-proxy's Issues

SP metadata not provided

I installed saml-auth-proxy from scratch with adfs backend. As described in your notes I want to get the sp metadata by running this command:

curl http://localhost:19001/saml/metadata

But I only got:

404 page not found

Iโ€˜m using the release 1.0.0 on RHEL x86. Any hint what happen ?

Error when with websockets

Getting the following error when the backend uses websockets.

"ERR failed to transfer backend response body: http: request method or response status code does not allow body"

Dev console shows "WebSocket connection to 'wss://xyz/ws' failed"

Are websockets not supported or is it a configuration issue?

Thanks

Redirects are not propagated

Hello!

Thanks for your nice work!

I've unfortunately identified an issue with it regarding the handling of HTTP 3xx (redirect) responses.

When the proxied server returns an HTTP redirect response the net/http Client will follow it before returning the final response (it will follow up to 10 redirects). As redirect responses are not returned to the client this will make him think that the content which is eventually returned belongs to the original URL requested while it actually belongs to a different one. As a consequence, relative links within the page are broken.

According to https://golang.org/pkg/net/http/#Client, this can be fixed by setting CheckRedirect on the Client to a function returning ErrUseLastResponse.

This can easily be tested by proxying an nginx server with autoindex and requesting the listing of a directory with an URL like http://proxy/path/to/directory (without a trailing slash) as nginx will redirect to an URL with a trailing slash http://proxy/path/to/directory/. With the redirect swallowed by the proxy, the client will get the directory listing and when clicking on any of them it will be directed to http://proxy/path/to/entry instead of the correct http://proxy/path/to/directory/entry.

Cheers,

Olivier

Support Allow IDP Initiated

Can we support the AllowIDPInitiated flag?

Trying to create a portal to an app behind this proxy and getting a Forbidden on the /saml/acs page after login. The error in the logs say:

ERROR: `InResponseTo` does not match any of the possible request IDs (expected [])

From some research it appears we need to enable the AllowIDPInitiated flag.

Thoughts?

IdP metadata from local file

First of all hello and thank you for this very interesting project!

I am trying to configure saml-auth-proxy with Jumpcloud.
Unfortunately it would seem that Jumpcloud does not expose a public URL where to fetch the XML.

However, after authentication, the metadata XML can be downloaded. Thus if saml-auth-proxy could open the metadata XML as a file this issue could be easily solved.

I might be able to contribute the feature myself if there's interest.

NOTE: to verify that the file loading was indeed the only blocker to implement Jumpcloud, I've served the file from a local web host and it works as expected.

Config to change cookie name

Ability to change the cookie name.

I have a conflicting cookie name I have no control of. Need to customize this one.

Feature Proposal: Support anonymous access to the backend

Background

I want to log in to Grafana using SAML while allowing anonymous access to the public dashboard. Here is the example configuration of such situation.

[auth.anonymous]
enabled = true
org_name = Public Org.
org_role = Viewer

[auth.proxy]
enabled = true

Current Situation

Currently, saml-auth-proxy always initiates SAML auth flow. It forces all users to sign in though Grafana allows anonymous access.

That behaviour is caused by use of RequireAccount in proxy server.

http.Handle("/", middleware.RequireAccount(app))

Proposal

saml-auth-proxy should support anonymous access to the backend app.

I made some prototype which works for my usecase. Changes can be found on the commit: kyori19@6642f8a.

In my implementation, almost all requests from users will be proxied to the backend without initiating/requiring SAML auth. However, when the user accesses to the login path /login, saml-auth-proxy initiates SAML auth flow and user can log in to the service. The login path /login will be accessed when the user clicks "Sign In" button on Grafana dashboard.

Problem

As my implementation is just a prototype and heavily adopted on my usecase, it has some problems.

  • I have commented out some features I won't use to reduce implementation cost.
  • The login path cannot be configured, it should be accessible via flags/envs.

Configurable cookie domain

We'd like to have the proxy at login.company.com and have apps behind the proxy at app.company.com.

Can we make the cookie domain configurable? So it can be set to the parent domain, say, .company.com.

saml-auth-proxy dropping URI part of backend-url

Hi,

So we've been continuing to work with your saml-auth-proxy, and I have been doing tests with different scenarios, e.g. one test is where the backend-url is a simple Apache hosted HTML page and we set the backend-url to the URL of that HTML page and that works.

Now I am testing with backend-url set to an a simple Apache hosted HTML page, but where the URL for that page is protected by OAM, and it is ALMOST working, but when it finally gets through part of the protocol where OAM has already authenticated the user (using a cert), it is not sending the request to the URL in the backend-url parameter. Instead, it appears to be sending the request to the URL that is the backend-url parameter, BUT with the URI part missing.

For example, I have:

-backend-url https://pxy.west.XXX.com:8443/ootbx509/index.html \

but instead of sending the final request to:

https://pxy.west.XXX.com:8443/ootbx509/index.html

it is ending the request to:

https://pxy.west.XXX.com:8443/

FYI, I also tried a test where I had both the backend-url and the new -static-relay-state set to the desired URL but when I tested with that, I got a 403/Forbidden when I tested.

Also FYI, I think we are "pretty close" because I did another test with just the backend-url parameter and again, it went to the "/" URI, then I manually added the /ootbx509/index.html to the URL in the address bar, and I got the desired test page back (i.e., OAM did allow the desired target request through).

Please advise.

Thanks,
Jim

Just plain THANK YOU!

Geoff, this little project of yours helped us a ton. Frankly it was exactly the piece of glue that was missing between a backend that doesn't natively support SAML and our in house SAML IDP.

Appreciate your work!
Thanks from Hannover, Germany!
Ralph

Allowing literal commas in options

Hi! I'm the guy from this issue: itzg/go-flagsfiller#31

If I had had noticed initially that you were the owner of both repos, I might have started here first. ๐Ÿ™‚

saml-auth-proxy seems to do almost everything I need, except for allowing comma-bearing values to -authorize-values. Thanks so much for making this. And for being so responsive with the library!

I have zero experience with golang, but I'm willing to at least try to write the code to allow this. Would you be willing to accept such a change?

I could just hard-change main.go:23 to stop splitting commas like I did for my own build as a stop-gap, but that doesn't seem the right thing. What would you suggest?

Thanks!

Trying it out: Does not access Grafana automatically

Bear with me for another "Trying it out" question:
After entering user and password in the SAMLTest's login page (user rick), it redirects to Grafana login page and stops there instead of login into Grafana. I notice that uname is blank.

logger=context userId=0 orgId=0 uname= t=2023-01-05T14:38:31.024938104Z level=info msg="Request Completed" method=GET >>path=/ status=302 remote_addr=127.0.0.1 time_ms=8 duration=8.13263ms size=29 referer= handler=/

What's wrong with my setup? Appreciate any hints.

Hendro

after login, the /_verify check redirects to the wrong URI

I have an app running at my-app.my-domain.com, and saml-auth-proxy running at sso.my-domain.com, and forward_auth setup to https://sso.my-domain.com/_verify.

Problem:

  1. user visits my-app.my-domain.com
  2. is redirected to login and logs in
  3. gets redirected to sso.my-domain.com/_verify instead of the original my-app.my-domain.com.

To help, the forward_auth protocol includes two headers to the /_verify request -- X-Forwarded-Method and X-Forwarded-Uri.

Potential solution?
The cookie tracker could detect the /_verify path and use x-forwarded-uri header instead of r.URL.String in line

If it helps, I have an old old fork that does this (probably not the best check): https://github.com/kennethklee/saml-auth-proxy/blob/4cba73af48ba5aebcb5f22d16a6231a542bcb112/server/request_tracker_cookie.go#L27-L34

Proxy not forwarding after SAML Response

Hi,

My apologies in advance, but one of my colleagues is doing the testing of the saml-auth-proxy and he reported that he is having a problem. I will provide what he told me. Please let me know if you have any questions?

"Can the proxy be used to forward the saml response to a specific destination? The proxy seems to be returning the correct response to the /acs (Assertion Consumer Service) endpoint, but then is not forwarding that response to the destination that we are trying to protect."

I have the command line he is using, but I have a meeting to go to and will post that to this issue after I am back.

Thanks!

Jim

Enhance for Traefik's ForwardAuth feature?

This is pretty cool. I've been struggling with getting a proper SAML library for Go, but haven't been successful with the in house one we use... Anyhow, this is interesting implementation of crewjam's SAML lib for some of us newbies at SAML.

Anyhow, I thought this would be really used if modified a bit as a Forward Auth server for Traefik.

azure adfs

what env value is for below
Login URL: https://login.microsoftonline.com/xyz/saml2
Azure AD Identifier: https://sts.windows.net/xyz

my env file is below

        - name: SAML_PROXY_BASE_URL
          value: https://{{ .Values.drop.url }}/
        - name: SAML_PROXY_BACKEND_URL
          value: http://localhost:9000
        - name: SAML_PROXY_IDP_METADATA_URL
          value: https://sts.lmn.com/FederationMetadata/2007-06/FederationMetadata.xml
        - name: SAML_PROXY_SP_CERT_PATH
          value: /ssl/tls.crt
        - name: SAML_PROXY_SP_KEY_PATH
          value: /ssl/tls.key
        - name: SAML_PROXY_NAME_ID_FORMAT
          value: persistent

Is it possible to have the proxy go to a URL (Relaystate)?

Hi,

It looks like the proxy is setting the RelayState to a number. I've been reading explanations about what it might do that, but would it be possible (some parameter or something) for us to set the RelayState to a real URL instead?

Also, I was wondering how to enable debugging? I've tried including the "-debug" parameter but it doesn't seem to be logging anything more when I do that.

Thanks!
Jim

Request tracker cookie domain

The crewjam/saml request tracker's cookie does not track the cookie domain. This prevents login directly from app.company.com.

Can we extend samlsp.RequestTrackerCookie to include the configured cookie domain?

We've been using login.company.com to redirect to app.company.com. Would be nice to do the whole login process from app.company.com

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.