You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
83 lines
2.4 KiB
83 lines
2.4 KiB
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")
|
|
}
|
|
|
|
// 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.
|
|
for _, service := range xrdsDoc.Xrd.Service {
|
|
// 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
|
|
if service.hasType("http://specs.openid.net/auth/2.0/server") {
|
|
opEndpoint = strings.TrimSpace(service.URI)
|
|
return
|
|
}
|
|
}
|
|
for _, service := range xrdsDoc.Xrd.Service {
|
|
// 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.
|
|
if service.hasType("http://specs.openid.net/auth/2.0/signon") {
|
|
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
|
|
}
|
|
|