This repository has been archived by the owner on Jun 9, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
sts-datatypes.go
307 lines (269 loc) · 8.66 KB
/
sts-datatypes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/*
* Federator, (C) 2017 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cmd
import (
"encoding/base64"
"encoding/xml"
"errors"
)
// Issuer - http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
// The <Issuer> element, with complex type NameIDType, provides information
// about the issuer of a SAML assertion or protocol message.
type Issuer struct {
XMLName xml.Name
SAML string `xml:"xmlns:saml,attr"`
URL string `xml:",innerxml"`
}
// Signature - An XML Signature that protects the integrity of and authenticates
// the issuer of the assertion
type Signature struct {
XMLName xml.Name
ID string `xml:"Id,attr"`
SignedInfo struct {
XMLName xml.Name
CanonicalizationMethod CanonicalizationMethod
SignatureMethod SignatureMethod
SamlsigReference struct {
XMLName xml.Name
URI string `xml:"URI,attr"`
Transforms Transforms `xml:",innerxml"`
DigestMethod DigestMethod `xml:",innerxml"`
DigestValue DigestValue `xml:",innerxml"`
}
}
SignatureValue struct {
XMLName xml.Name
Value string `xml:",innerxml"`
}
KeyInfo KeyInfo
}
// KeyInfo - SAML does not require the use of
// <ds:KeyInfo>, nor does it impose any restrictions
// on its use. Therefore, <ds:KeyInfo> MAY be absent.
type KeyInfo struct {
XMLName xml.Name
X509Data struct {
XMLName xml.Name
X509Certificate X509Certificate `xml:",innerxml"`
} `xml:",innerxml"`
}
// CanonicalizationMethod - Use of Exclusive Canonicalization ensures
// that signatures created over SAML messages embedded in an XML
// context can be verified independent of that context.
type CanonicalizationMethod struct {
XMLName xml.Name
Algorithm string `xml:"Algorithm,attr"`
}
// SignatureMethod - defines algorithm used to generate assertion signature.
type SignatureMethod struct {
XMLName xml.Name
Algorithm string `xml:"Algorithm,attr"`
}
// Transforms - Signatures in SAML messages SHOULD NOT contain transforms
// other than the enveloped signature transform (with the identifier
// http://www.w3.org/2000/09/xmldsig#enveloped-signature) or the exclusive
//
// Canonicalization transforms (with the identifier
// http://www.w3.org/2001/10/xml-exc-c14n# or
// http://www.w3.org/2001/10/xml-exc-c14n#WithComments).
// Verifiers of signatures MAY reject signatures that contain other
// transform algorithms as invalid. If they do not, verifiers MUST
// ensure that no content of the SAML message is excluded from the
// signature. This can be accomplished by establishing out-of-band
// agreement as to what transforms are acceptable, or by applying
// the transforms manually to the content and reverifying the result
// as consisting of the same SAML message.
type Transforms struct {
XMLName xml.Name
Transform []struct {
XMLName xml.Name
Algorithm string `xml:"Algorithm,attr"`
}
}
// DigestMethod - algorithm used for generating the digest.
type DigestMethod struct {
XMLName xml.Name
Algorithm string `xml:"Algorithm,attr"`
}
// DigestValue - digest value.
type DigestValue struct {
XMLName xml.Name
}
// X509Certificate - base64 encoded x.509 certificate data.
type X509Certificate struct {
XMLName xml.Name
Cert string `xml:",innerxml"`
}
// Response - saml assertion response obtained after parsing
// base64 encoded SAML assertion response from identity provider.
type Response struct {
XMLName xml.Name
SAMLP string `xml:"xmlns:samlp,attr"`
SAML string `xml:"xmlns:saml,attr"`
SAMLSIG string `xml:"xmlns:samlsig,attr"`
Destination string `xml:"Destination,attr"`
ID string `xml:"ID,attr"`
Version string `xml:"Version,attr"`
IssueInstant string `xml:"IssueInstant,attr"`
InResponseTo string `xml:"InResponseTo,attr"`
Issuer Issuer `xml:"Issuer"`
Signature Signature `xml:"Signature"`
Status Status `xml:"Status"`
// Assertion Assertion `xml:"Assertion"` Not implemented yet.
// This is kept here for future use.
origSAMLAssertion string
}
// Status - <Status> element contains a code representing
// the status of the activity carried out in response to
// the corresponding request.
type Status struct {
XMLName xml.Name
StatusCode struct {
XMLName xml.Name
Value string `xml:",attr"`
} `xml:"StatusCode"`
}
// Assertion - contains assertions if any.
type Assertion struct {
XMLName xml.Name
ID string `xml:"ID,attr"`
Version string `xml:"Version,attr"`
XS string `xml:"xmlns:xs,attr"`
XSI string `xml:"xmlns:xsi,attr"`
SAML string `xml:"xmlns:saml,attr"`
IssueInstant string `xml:"IssueInstant,attr"`
Issuer Issuer `xml:"Issuer"`
Subject Subject
Conditions Conditions
AuthnStatements []AuthnStatement `xml:"AuthnStatement,omitempty"`
AttributeStatement AttributeStatement
}
// AuthnContextClassRef --
type AuthnContextClassRef struct {
XMLName xml.Name
SAML string `xml:"xmlns:saml,attr"`
Transport string `xml:",innerxml"`
}
// AuthnStatement --
type AuthnStatement struct {
XMLName xml.Name
AuthnInstant string `xml:",attr"`
SessionNotOnOrAfter string `xml:",attr,omitempty"`
SessionIndex string `xml:",attr,omitempty"`
AuthnContext AuthnContext `xml:"AuthnContext"`
}
// AuthnContext --
type AuthnContext struct {
XMLName xml.Name
AuthnContextClassRef AuthnContextClassRef `xml:"AuthnContextClassRef"`
}
// Conditions --
type Conditions struct {
XMLName xml.Name
NotBefore string `xml:",attr"`
NotOnOrAfter string `xml:",attr"`
AudienceRestrictions []AudienceRestriction `xml:"AudienceRestriction,omitempty"`
}
// AudienceRestriction --
type AudienceRestriction struct {
XMLName xml.Name
Audiences []Audience `xml:"Audience"`
}
// Audience --
type Audience struct {
XMLName xml.Name
Value string `xml:",innerxml"`
}
// Subject --
type Subject struct {
XMLName xml.Name
NameID NameID
SubjectConfirmation SubjectConfirmation
}
// SubjectConfirmation --
type SubjectConfirmation struct {
XMLName xml.Name
Method string `xml:",attr"`
SubjectConfirmationData SubjectConfirmationData
}
// SubjectConfirmationData --
type SubjectConfirmationData struct {
XMLName xml.Name
InResponseTo string `xml:",attr"`
NotOnOrAfter string `xml:",attr"`
Recipient string `xml:",attr"`
}
// NameID --
type NameID struct {
XMLName xml.Name
Format string `xml:",attr"`
SPNameQualifier string `xml:",attr,omitempty"`
Value string `xml:",innerxml"`
}
// AttributeValue --
type AttributeValue struct {
XMLName xml.Name
Type string `xml:"xsi:type,attr"`
Value string `xml:",innerxml"`
}
// Attribute --
type Attribute struct {
XMLName xml.Name
Name string `xml:",attr"`
FriendlyName string `xml:",attr,omitempty"`
NameFormat string `xml:",attr"`
AttributeValues []AttributeValue `xml:"AttributeValue"`
}
// AttributeStatement --
type AttributeStatement struct {
XMLName xml.Name
Attributes []Attribute `xml:"Attribute"`
}
// Validate - validate the saml response, this is a non-exhaustive
// check currently validates only
// - A valid SAML version
// - A valid ID
// - A valid signature value
func (r *Response) Validate() error {
if r.Version != "2.0" {
return errors.New("Unsupported SAML Version")
}
if len(r.ID) == 0 {
return errors.New("Missing ID attribute on SAML Response")
}
if len(r.Signature.SignatureValue.Value) == 0 {
return errors.New("No signature value found")
}
return nil
}
// ParseSAMLResponse - parses base64 encoded SAML assertion response XML.
func ParseSAMLResponse(samlAssertion string) (*Response, error) {
response := Response{}
bytesXML, err := base64.StdEncoding.DecodeString(samlAssertion)
if err != nil {
return nil, err
}
if err = xml.Unmarshal(bytesXML, &response); err != nil {
return nil, err
}
if err = response.Validate(); err != nil {
return nil, err
}
// Save the original base64 encoded value.
response.origSAMLAssertion = samlAssertion
// Success.
return &response, nil
}