crewjam / saml

SAML library for go
BSD 2-Clause "Simplified" License
969 stars 435 forks source link

AWS SSO 'no access error' with Custom SAML application #379

Closed MatteoGioioso closed 3 years ago

MatteoGioioso commented 3 years ago

I am trying to setup a Custom SAML 2.0 application with AWS SSO. However I have the following error from network tab:

Status code 403
{"message":"No access","__type":"com.amazonaws.switchboard.portal#ForbiddenException"}

And this one displayed in the UI:

AWS SSO console error

Two considerations that might cause this error:

  1. My SP testing server is running in localhost
  2. I am using self-signed certificates:
    openssl req -x509 -newkey rsa:2048 -keyout myservice.key -out myservice.cert -days 365 -nodes -subj "/CN=localhost:9000"

or

openssl req -x509 -out saml-proxy.crt -keyout saml-proxy.key \
  -newkey rsa:2048 -nodes -sha256 \
  -subj '/CN=localhost' -extensions EXT -config <( \
   printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

If this still does not tell you anything then I will describe more below.

Update

I have also tried with using an EC2 instance using self signed certificate, but still the same issue.

Update 2

I have also provided valid AWS ACM certificates to my domain and it still does not work.


More details

This is the server code which is from the the library I am using

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %s!", samlsp.AttributeFromContext(r.Context(), "cn"))
}

func main() {
    keyPair, err := tls.LoadX509KeyPair("myservice.cert", "myservice.key")
    if err != nil {
        panic(err) // TODO handle error
    }
    keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
    if err != nil {
        panic(err) // TODO handle error
    }

    idpMetadataURL, err := url.Parse("https://portal.sso.<my aws region>.amazonaws.com/saml/metadata/<some jewbrish id>")
    if err != nil {
        panic(err) // TODO handle error
    }
    idpMetadata, err := samlsp.FetchMetadata(context.Background(), http.DefaultClient,
        *idpMetadataURL)
    if err != nil {
        panic(err) // TODO handle error
    }

    rootURL, err := url.Parse("http://localhost:9000")
    if err != nil {
        panic(err) // TODO handle error
    }

    samlSP, _ := samlsp.New(samlsp.Options{
        URL:            *rootURL,
        Key:            keyPair.PrivateKey.(*rsa.PrivateKey),
        Certificate:    keyPair.Leaf,
        IDPMetadata: idpMetadata,
    })
    app := http.HandlerFunc(hello)
    http.Handle("/hello", samlSP.RequireAccount(app))
    http.Handle("/saml/", samlSP)
    http.ListenAndServe(":8000", nil)
}

This server expose an endpoint where the IDP can get fetch my auto generated metadata.

curl -o metadata.xml http://localhost:9000/saml/metadata

Those are my metadata:

<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" validUntil="2021-09-13T03:37:23.951Z" entityID="http://localhost:9000/saml/metadata">
  <SPSSODescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" validUntil="2021-09-13T03:37:23.951204335Z" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" AuthnRequestsSigned="false" WantAssertionsSigned="true">
    <KeyDescriptor use="encryption">
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <X509Data>
          <X509Certificate>xxxxxxxxxx</X509Certificate>
        </X509Data>
      </KeyInfo>
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"></EncryptionMethod>
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes192-cbc"></EncryptionMethod>
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"></EncryptionMethod>
      <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"></EncryptionMethod>
    </KeyDescriptor>
    <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:9000/saml/slo" ResponseLocation="http://localhost:9000/saml/slo"></SingleLogoutService>
    <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:9000/saml/acs" index="1"></AssertionConsumerService>
  </SPSSODescriptor>
</EntityDescriptor>

I have uploaded those into AWS SSO and it correctly parsed it, the following in the configuration of my AWS SSO Custom application:

Full AWS SSO custom app configuration

When I hit the localhost:9000/hello the application will be successfully redirected to the AWS SSO login console, but the that error happens. I have also tested the application using this website: https://samltest.id/upload.php and it worked fine.

PS: is there a way to debug this? I cannot how to inject a logger into the application

MatteoGioioso commented 3 years ago

I have found the solution, the problem was in the attributes mapping, this is the configuration I had to use in order to make it work.

enter image description here

Note the transient format option, in my previous configuration it was unspecified

mikemartin1090 commented 2 years ago

I was getting a similar 403 error and I figure I will share with the world so hopefully you learn from my mistakes... I simply typed in what I thought I saw from a YouTube video was a . (${user.email}), when in reality it is supposed to be a : (${user:email}). This fixed it right up. Another reminder to copy and paste from the documents (specifically this document).