forked from yohcop/openid-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xrds.go
80 lines (72 loc) · 2.36 KB
/
xrds.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
package openid
import (
"encoding/xml"
"errors"
"strings"
)
// TODO: As per 11.2 in openid 2 specs, a service may have multiple
// URIs. We don't care for discovery really, but we do care for
// verification though.
type XrdsIdentifier struct {
Type []string `xml:"Type"`
Uri string `xml:"URI"`
LocalId string `xml:"LocalID"`
Priority int `xml:"priority,attr"`
}
type Xrd struct {
Service []*XrdsIdentifier `xml:"Service"`
}
type XrdsDocument struct {
XMLName xml.Name `xml:"XRDS"`
Xrd *Xrd `xml:"XRD"`
}
func parseXrds(input []byte) (opEndpoint, opLocalId string, err error) {
xrdsDoc := &XrdsDocument{}
err = xml.Unmarshal(input, xrdsDoc)
if err != nil {
return
}
if xrdsDoc.Xrd == nil {
return "", "", errors.New("XRDS document missing XRD tag")
}
for _, service := range xrdsDoc.Xrd.Service {
// 7.3.2.2. Extracting Authentication Data
// Once the Relying Party has obtained an XRDS document, it
// MUST first search the document (following the rules
// described in [XRI_Resolution_2.0]) for an OP Identifier
// Element. If none is found, the RP will search for a Claimed
// Identifier Element.
if service.hasType("http://specs.openid.net/auth/2.0/server") {
// 7.3.2.1.1. OP Identifier Element
// An OP Identifier Element is an <xrd:Service> element with the
// following information:
// An <xrd:Type> tag whose text content is
// "http://specs.openid.net/auth/2.0/server".
// An <xrd:URI> tag whose text content is the OP Endpoint URL
opEndpoint = strings.TrimSpace(service.Uri)
return
} else if service.hasType("http://specs.openid.net/auth/2.0/signon") {
// 7.3.2.1.2. Claimed Identifier Element
// A Claimed Identifier Element is an <xrd:Service> element
// with the following information:
// An <xrd:Type> tag whose text content is
// "http://specs.openid.net/auth/2.0/signon".
// An <xrd:URI> tag whose text content is the OP Endpoint
// URL.
// An <xrd:LocalID> tag (optional) whose text content is the
// OP-Local Identifier.
opEndpoint = strings.TrimSpace(service.Uri)
opLocalId = strings.TrimSpace(service.LocalId)
return
}
}
return "", "", errors.New("Could not find a compatible service")
}
func (xrdsi *XrdsIdentifier) hasType(tpe string) bool {
for _, t := range xrdsi.Type {
if t == tpe {
return true
}
}
return false
}