func (handler *queryHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { decoder := xml.NewDecoder(request.Body) var attributeEnv attributes.AttributeQueryEnv err := decoder.Decode(&attributeEnv) // TODO determine if this is the appropriate error response if err != nil { http.Error(writer, err.Error(), 500) return } // TODO validate attributeEnv before proceeding query := attributeEnv.Body.Query name := query.Subject.NameID.Value format := query.Subject.NameID.Format user := &protocol.AuthenticatedUser{Name: name, Format: format} atts, err := handler.retriever.Retrieve(user) // TODO determine if this is the appropriate error response if err != nil { http.Error(writer, err.Error(), 500) return } var attrResp attributes.AttributeRespEnv resp := &attrResp.Body.Response resp.ID = protocol.NewID() resp.InResponseTo = query.ID resp.Version = "2.0" now := time.Now() resp.IssueInstant = now resp.Issuer = saml.NewIssuer(handler.entityId) a := &saml.Assertion{} a.Issuer = resp.Issuer a.IssueInstant = now a.ID = protocol.NewID() a.Version = "2.0" a.Subject = &saml.Subject{} a.Subject.NameID = query.Subject.NameID a.AttributeStatement = saml.NewAttributeStatement(atts) a.Conditions = &saml.Conditions{} a.Conditions.NotBefore = now fiveMinutes, _ := time.ParseDuration("5m") fiveFromNow := now.Add(fiveMinutes) a.Conditions.NotOnOrAfter = fiveFromNow a.Conditions.AudienceRestriction = &saml.AudienceRestriction{Audience: query.Issuer} resp.Status = protocol.NewStatus(true) resp.Assertion = a signature, err := handler.signer.Sign(a) // TODO determine if this is the appropriate error response if err != nil { http.Error(writer, err.Error(), 500) return } a.Signature = signature // TODO handle these errors. Probably can't do anything besides log, as we've already started to write the // response. _, err = writer.Write([]byte(xml.Header)) encoder := xml.NewEncoder(writer) err = encoder.Encode(attrResp) err = encoder.Flush() }
func (generator *defaultGenerator) Generate(user *AuthenticatedUser, authnRequest *AuthnRequest, attributes map[string][]string) *Response { s := &Response{} s.Version = "2.0" s.ID = NewID() now := time.Now() fiveMinutes, _ := time.ParseDuration("5m") fiveFromNow := now.Add(fiveMinutes) s.IssueInstant = now s.Status = NewStatus(true) s.InResponseTo = authnRequest.ID s.Issuer = saml.NewIssuer(generator.entityId) assertion := &saml.Assertion{} assertion.ID = NewID() assertion.IssueInstant = now assertion.Version = "2.0" assertion.Issuer = s.Issuer nameId := &saml.NameID{} nameId.Format = user.Format nameId.NameQualifier = generator.entityId nameId.SPNameQualifier = authnRequest.Issuer nameId.Value = user.Name confirmation := &saml.SubjectConfirmation{} confirmation.Method = "urn:oasis:names:tc:SAML:2.0:cm:bearer" confData := &saml.SubjectConfirmationData{} confData.Address = user.IP confData.InResponseTo = authnRequest.ID confData.Recipient = authnRequest.AssertionConsumerServiceURL confData.NotOnOrAfter = fiveFromNow confirmation.SubjectConfirmationData = confData subject := &saml.Subject{NameID: nameId, SubjectConfirmation: confirmation} assertion.Subject = subject conditions := &saml.Conditions{} conditions.NotOnOrAfter = fiveFromNow conditions.NotBefore = now audRestriction := &saml.AudienceRestriction{Audience: authnRequest.Issuer} conditions.AudienceRestriction = audRestriction assertion.Conditions = conditions authnStatement := &saml.AuthnStatement{} authnStatement.AuthnInstant = now authnStatement.SessionIndex = uuid.NewV4().String() subLoc := &saml.SubjectLocality{Address: confData.Address} authnStatement.SubjectLocality = subLoc authContext := &saml.AuthnContext{AuthnContextClassRef: user.Context} authnStatement.AuthnContext = authContext assertion.AuthnStatement = authnStatement assertion.AttributeStatement = saml.NewAttributeStatement(attributes) s.Assertion = assertion return s }
func (handler *artifactHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) { decoder := xml.NewDecoder(request.Body) var resolveEnv protocol.ArtifactResolveEnvelope err := decoder.Decode(&resolveEnv) // TODO confirm appropriate error response for this service if err != nil { http.Error(writer, err.Error(), 500) return } // TODO validate resolveEnv before proceeding artifact := resolveEnv.Body.ArtifactResolve.Artifact var response protocol.Response err = handler.store.Retrieve(artifact, &response) // TODO confirm appropriate error response for this service if err != nil { http.Error(writer, err.Error(), 500) return } artResponseEnv := protocol.ArtifactResponseEnvelope{} artResponse := &artResponseEnv.Body.ArtifactResponse artResponse.ID = uuid.NewV4().String() now := time.Now() artResponse.IssueInstant = now artResponse.InResponseTo = resolveEnv.Body.ArtifactResolve.ID artResponse.Version = "2.0" artResponse.Issuer = saml.NewIssuer(handler.entityId) artResponse.Status = protocol.NewStatus(true) artResponse.Response = response signature, err := handler.signer.Sign(response.Assertion) // TODO confirm appropriate error response for this service if err != nil { http.Error(writer, err.Error(), 500) return } response.Assertion.Signature = signature // TODO handle these errors. Probably can't do anything besides log, as we've already started to write the // response. _, err = writer.Write([]byte(xml.Header)) encoder := xml.NewEncoder(writer) err = encoder.Encode(artResponseEnv) err = encoder.Flush() }