{"id":13735002,"url":"https://github.com/RobotsAndPencils/go-saml","last_synced_at":"2025-05-08T11:31:47.382Z","repository":{"id":57480143,"uuid":"39785964","full_name":"RobotsAndPencils/go-saml","owner":"RobotsAndPencils","description":"A just good enough SAML client library written in Go.","archived":true,"fork":false,"pushed_at":"2023-11-15T19:43:36.000Z","size":33,"stargazers_count":132,"open_issues_count":24,"forks_count":82,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-05-18T15:40:03.433Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RobotsAndPencils.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-07-27T16:43:59.000Z","updated_at":"2024-05-17T16:43:40.000Z","dependencies_parsed_at":"2023-01-18T22:45:36.624Z","dependency_job_id":"60160fc0-635d-4b5e-ae3b-1fdba643950b","html_url":"https://github.com/RobotsAndPencils/go-saml","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobotsAndPencils%2Fgo-saml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobotsAndPencils%2Fgo-saml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobotsAndPencils%2Fgo-saml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobotsAndPencils%2Fgo-saml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobotsAndPencils","download_url":"https://codeload.github.com/RobotsAndPencils/go-saml/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224727173,"owners_count":17359532,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T03:01:01.979Z","updated_at":"2024-11-15T03:31:20.933Z","avatar_url":"https://github.com/RobotsAndPencils.png","language":"Go","funding_links":[],"categories":["Go","Programming Language Libraries"],"sub_categories":["Go"],"readme":"## Unsupported\n\nUnfortunately, the decision has been made to sunset support for this project. We thank everyone for supporting and utilizing the project. \n\nCouple of alternatives could be https://github.com/russellhaering/gosaml2 or maybe https://github.com/crewjam/saml. These are solely suggestions to start the look for an alternative and are not an endorsement by RNP. We've not done a code review of these repos. We recommend doing a vetting pass on the repository prior to integrating any third party dependencies.\n\ngo-saml\n======\n\n[![Build Status](https://travis-ci.org/RobotsAndPencils/go-saml.svg?branch=master)](https://travis-ci.org/RobotsAndPencils/go-saml)\n\nA just good enough SAML client library written in Go. This library is by no means complete and has been developed\nto solve several specific integration efforts. However, it's a start, and it would be great to see\nit evolve into a more fleshed out implemention.\n\nInspired by the early work of [Matt Baird](https://github.com/mattbaird/gosaml).\n\nThe library supports:\n\n* generating signed/unsigned AuthnRequests\n* validating signed AuthnRequests\n* generating service provider metadata\n* generating signed Responses\n* validating signed Responses\n\n\nInstallation\n------------\n\n    $ go get github.com/RobotsAndPencils/go-saml\n\nHere's a convenient way to generate a certificate:\n\n    curl -sSL https://raw.githubusercontent.com/frntn/x509-san/master/gencert.sh | CRT_CN=\"mycert\"  bash\n\n\nUsage\n-----\n\nBelow are samples to show how you might use the library.\n\n### Generating Signed AuthnRequests\n\n```go\nsp := saml.ServiceProviderSettings{\n  PublicCertPath:              \"../default.crt\",\n  PrivateKeyPath:              \"../default.key\",\n  IDPSSOURL:                   \"http://idp/saml2\",\n  IDPSSODescriptorURL:         \"http://idp/issuer\",\n  IDPPublicCertPath:           \"idpcert.crt\",\n  SPSignRequest:               \"true\",\n  AssertionConsumerServiceURL: \"http://localhost:8000/saml_consume\",\n}\nsp.Init()\n\n// generate the AuthnRequest and then get a base64 encoded string of the XML\nauthnRequest := sp.GetAuthnRequest()\nb64XML, err := authnRequest.EncodedSignedString(sp.PrivateKeyPath)\nif err != nil {\n  panic(err)\n}\n\n// for convenience, get a URL formed with the SAMLRequest parameter\nurl, err := saml.GetAuthnRequestURL(sp.IDPSSOURL, b64XML)\nif err != nil {\n  panic(err)\n}\n\n// below is bonus for how you might respond to a request with a form that POSTs to the IdP\ndata := struct {\n  Base64AuthRequest string\n  URL               string\n}{\n  Base64AuthRequest: b64XML,\n  URL:               url,\n}\n\nt := template.New(\"saml\")\nt, err = t.Parse(\"\u003chtml\u003e\u003cbody style=\\\"display: none\\\" onload=\\\"document.frm.submit()\\\"\u003e\u003cform method=\\\"post\\\" name=\\\"frm\\\" action=\\\"{{.URL}}\\\"\u003e\u003cinput type=\\\"hidden\\\" name=\\\"SAMLRequest\\\" value=\\\"{{.Base64AuthRequest}}\\\" /\u003e\u003cinput type=\\\"submit\\\" value=\\\"Submit\\\" /\u003e\u003c/form\u003e\u003c/body\u003e\u003c/html\u003e\")\n\n// how you might respond to a request with the templated form that will auto post\nt.Execute(w, data)\n```\n\n### Validating a received SAML Response\n\n\n```go\nresponse = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n  encodedXML := r.FormValue(\"SAMLResponse\")\n\n  if encodedXML == \"\" {\n    httpcommon.SendBadRequest(w, \"SAMLResponse form value missing\")\n    return\n  }\n\n  response, err := saml.ParseEncodedResponse(encodedXML)\n  if err != nil {\n    httpcommon.SendBadRequest(w, \"SAMLResponse parse: \"+err.Error())\n    return\n  }\n\n  err = response.Validate(\u0026sp)\n  if err != nil {\n    httpcommon.SendBadRequest(w, \"SAMLResponse validation: \"+err.Error())\n    return\n  }\n\n  samlID := response.GetAttribute(\"uid\")\n  if samlID == \"\" {\n    httpcommon.SendBadRequest(w, \"SAML attribute identifier uid missing\")\n    return\n  }\n\n  //...\n}\n```\n\n### Service provider metadata\n\n```go\nfunc samlMetadataHandler(sp *saml.ServiceProviderSettings) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tmd, err := sp.GetEntityDescriptor()\n\t\tif err != nil {\n      w.WriteHeader(500)\n      w.Write([]byte(\"Error: \" + err.Error()))\n\t\t\treturn\n\t\t}\n\n\t\tw.Header().Set(\"Content-Type\", \"application/xml\")\n\t\tw.Write([]byte(md))\n\t})\n}\n```\n\n### Receiving a authnRequest\n\n```go\nb64Request := r.URL.Query().Get(\"SAMLRequest\")\nif b64Request == \"\" {\n  w.WriteHeader(400)\n  w.Write([]byte(\"SAMLRequest parameter missing\"))\n  return\n}\n\ndefated, err := base64.StdEncoding.DecodeString(b64Request)\nif err != nil {\n  w.WriteHeader(500)\n  w.Write([]byte(\"Error: \" + err.Error()))\n  return\n}\n\n// enflate and unmarshal\nvar buffer bytes.Buffer\nrdr := flate.NewReader(bytes.NewReader(defated))\nio.Copy(\u0026buffer, rdr)\nvar authnRequest saml.AuthnRequest\n\nerr = xml.Unmarshal(buffer.Bytes(), \u0026authnRequest)\nif err != nil {\n  w.WriteHeader(500)\n  w.Write([]byte(\"Error: \" + err.Error()))\n  return\n}\n\nif authnRequest.Issuer.Url != issuerURL {\n  w.WriteHeader(500)\n  w.Write([]byte(\"unauthorized issuer \"+authnRequest.Issuer.Url))\n  return\n}\n\n```\n\n### Creating a SAML Response (if acting as an IdP)\n\n```go\nissuer := \"http://localhost:8000/saml\"\nauthnResponse := saml.NewSignedResponse()\nauthnResponse.Issuer.Url = issuer\nauthnResponse.Assertion.Issuer.Url = issuer\nauthnResponse.Signature.KeyInfo.X509Data.X509Certificate.Cert = stringValueOfCert\nauthnResponse.Assertion.Subject.NameID.Value = userIdThatYouAuthenticated\nauthnResponse.AddAttribute(\"uid\", userIdThatYouAuthenticated)\nauthnResponse.AddAttribute(\"email\", \"someone@domain\")\nauthnResponse.Assertion.Subject.SubjectConfirmation.SubjectConfirmationData.InResponseTo = authnRequestIdRespondingTo\nauthnResponse.InResponseTo = authnRequestIdRespondingTo\nauthnResponse.Assertion.Subject.SubjectConfirmation.SubjectConfirmationData.Recipient = issuer\n\n// signed XML string\nsigned, err := authnResponse.SignedString(\"/path/to/private.key\")\n\n// or signed base64 encoded XML string\nb64XML, err := authnResponse.EncodedSignedString(\"/path/to/private.key\")\n\n```\n\n\n### Contributing\n\nWould love any contributions you having including better documentation, tests, or more robust functionality.\n\n    git clone git@github.com:RobotsAndPencils/go-saml.git\n    make init\n    make test\n\n### Contact\n\n[![Robots \u0026 Pencils Logo](http://f.cl.ly/items/2W3n1r2R0j2p2b3n3j3c/rnplogo.png)](http://www.robotsandpencils.com)\n\nMade with :heart: by Robots \u0026 Pencils ([@robotsNpencils](https://twitter.com/robotsNpencils))\n\n#### Maintainers\n\n- [Mike Brevoort](http://github.com/mbrevoort) ([@mbrevoort](https://twitter.com/mbrevoort))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobotsAndPencils%2Fgo-saml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRobotsAndPencils%2Fgo-saml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobotsAndPencils%2Fgo-saml/lists"}