FAQ | This is a LIVE service | Changelog

Skip to content
Snippets Groups Projects
Commit 35d72309 authored by Dr Rich Wareham's avatar Dr Rich Wareham
Browse files

add support for v1,2 and 3 responses

parent cfb99d6a
No related branches found
No related tags found
No related merge requests found
......@@ -14,6 +14,10 @@ var requiredParams = []string{"ver", "url"}
// is used as an O(1) lookup to determine if a given parameter name is valid.
var allowedParams = map[string]bool{}
// knownVersions is a list of known versions of the protocol. An authetication
// request is invalid if the version does not match one of these versions.
var knownVersions = []string{"1", "2", "3"}
// AuthRequest represents the parsed value of an authentication request.
type AuthRequest struct {
// The version of the protocol being requested. Must be "1", "2" or "3".
......@@ -107,7 +111,13 @@ func NewAuthRequest(request *http.Request) (*AuthRequest, error) {
URL: url,
}
return ar, nil
for _, ver := range knownVersions {
if ver == ar.Version {
return ar, nil
}
}
return nil, fmt.Errorf("Unkown protocol version: %v", ar.Version)
}
// isSafeText returns true if the passed string is ASCII and does not
......
......@@ -133,6 +133,28 @@ func newGetRequest(t *testing.T, vs *url.Values) *http.Request {
return r
}
func TestBadVersion(t *testing.T) {
vs := newGoodValues()
vs.Set("ver", "bas")
r := newGetRequest(t, vs)
checkNewAuthRequestFails(t, r)
}
func TestGoodVersions(t *testing.T) {
for _, ver := range []string{"1", "2", "3"} {
vs := newGoodValues()
vs.Set("ver", ver)
r := newGetRequest(t, vs)
_, err := NewAuthRequest(r)
if err != nil {
t.Fatal(err)
}
}
}
func newGoodValues() *url.Values {
return &url.Values{
"ver": {"3"},
......
......@@ -16,6 +16,9 @@ import (
)
const (
// StatusUnset indicates the status has not yet been set
StatusUnset = ""
// StatusSuccess indicates authentication succeeded.
StatusSuccess = "200"
......@@ -45,6 +48,9 @@ const (
// StatusDeclined indicates that this WLS declined to provide authentication services
// to the WAA.
StatusDeclined = "570"
// AuthPassword is the password authentication auth type.
AuthPassword = "pwd"
)
// AuthResponse represents a response to a WAA from a WLS. An encoded and signed form of the
......@@ -121,19 +127,31 @@ func NewAuthResponse(req *AuthRequest) (*AuthResponse, error) {
// ResponseData converts the response into a parameter string suitable for signing.
func (r *AuthResponse) ResponseData() string {
values := []string{
"3",
r.Version,
r.Status,
r.Message,
r.IssueTime.UTC().Format("20060102T150405Z"),
r.Identifier,
r.URL.String(),
r.Principal,
strings.Join(r.PTags, ","),
}
if r.Status == StatusSuccess {
values = append(values, r.Principal)
} else {
values = append(values, "")
}
if r.Version == "3" {
values = append(values, strings.Join(r.PTags, ","))
}
values = append(
values,
r.AuthType,
strings.Join(r.SSO, ","),
strconv.FormatInt(int64(r.Lifetime.Seconds()), 10),
r.Params,
}
)
data := []string{}
for _, v := range values {
......@@ -151,6 +169,10 @@ func (r *AuthResponse) SignedResponseData(rand io.Reader, kid int64, priv *rsa.P
return "", fmt.Errorf("Key id '%v' must be greater than zero", kid)
}
if r.Status == StatusUnset {
return "", fmt.Errorf("Status not yet set")
}
rdata := r.ResponseData()
// The response data must first be hash-ed using the SHA-1 hash
......@@ -184,6 +206,11 @@ func (r *AuthResponse) SignedResponseURL(rand io.Reader, kid int64, priv *rsa.Pr
panic(err)
}
// For version 1 requests, the existing query string is ignored
if r.Version == "1" {
u.RawQuery = ""
}
vs := u.Query()
vs.Add("WLS-Response", data)
u.RawQuery = vs.Encode()
......@@ -191,6 +218,18 @@ func (r *AuthResponse) SignedResponseURL(rand io.Reader, kid int64, priv *rsa.Pr
return u, nil
}
// SetSuccess sets the response as successful for the passed principal. For compatibility
// with the Raven implementation, this will also add the "current" PTag for v3 responses.
func (r *AuthResponse) SetSuccess(principal string, authType string) {
r.Status = StatusSuccess
r.Principal = principal
r.AuthType = authType
if r.Version == "3" {
r.PTags = append(r.PTags, "current")
}
}
// escapeResponseComponent escapes "!" and "%" characters as described in the WebAuth spec
// by replacing them with "%21" and "%25" respectively.
func escapeResponseComponent(s string) string {
......
......@@ -23,6 +23,8 @@ func TestSignResponse(t *testing.T) {
t.Fatal(err)
}
resp.SetSuccess("spqr1", AuthPassword)
key := newKey(t)
r, err := resp.SignedResponseData(rand.Reader, 1, key)
if err != nil {
......
File added
......@@ -9,7 +9,7 @@ import (
"log"
"net/http"
"github.com/rjw57/ucamwls"
ucamwls "../.."
)
const keyPEMData = `
......@@ -59,10 +59,7 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
return
}
resp.Principal = "spqr1"
resp.Status = ucamwls.StatusSuccess
resp.AuthType = "pwd"
resp.PTags = []string{"current"}
resp.SetSuccess("spqr1", ucamwls.AuthPassword)
url, err := resp.SignedResponseURL(rand.Reader, 1, key)
if err != nil {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment