cas

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2017 License: MIT Imports: 14 Imported by: 0

README

CAS Client library

CAS provides a http package compatible client implementation for use with securing http frontends in golang.

import "gopkg.in/cas.v1"

Examples and Documentation

Documentation is available at: http://godoc.org/gopkg.in/cas.v1 Examples are included in the documentation but are also available in the _examples directory.

Documentation

Overview

Package cas implements a CAS client.

CAS is a protocol which provides authentication and authorisation for securing typically HTTP based services.

References:

[PROTOCOL]: http://jasig.github.io/cas/4.0.x/protocol/CAS-Protocol.html
Example
package main

import (
	"bytes"
	"flag"
	"fmt"
	"html/template"
	"net/http"
	"net/url"

	"github.com/golang/glog"

	"gopkg.in/cas.v1"
)

type myHandler struct{}

var MyHandler = &myHandler{}
var casURL string

func init() {
	flag.StringVar(&casURL, "url", "", "CAS server URL")
}

func main() {
	Example()
}

func main() {
	flag.Parse()

	if casURL == "" {
		flag.Usage()
		return
	}

	glog.Info("Starting up")

	m := http.NewServeMux()
	m.Handle("/", MyHandler)

	url, _ := url.Parse(casURL)
	client := cas.NewClient(&cas.Options{
		URL: url,
	})

	server := &http.Server{
		Addr:    ":8080",
		Handler: client.Handle(m),
	}

	if err := server.ListenAndServe(); err != nil {
		glog.Infof("Error from HTTP Server: %v", err)
	}

	glog.Info("Shutting down")
}

type templateBinding struct {
	Username   string
	Attributes cas.UserAttributes
}

func (h *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if !cas.IsAuthenticated(r) {
		cas.RedirectToLogin(w, r)
		return
	}

	if r.URL.Path == "/logout" {
		cas.RedirectToLogout(w, r)
		return
	}

	w.Header().Add("Content-Type", "text/html")

	tmpl, err := template.New("index.html").Parse(index_html)

	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, error_500, err)
		return
	}

	binding := &templateBinding{
		Username:   cas.Username(r),
		Attributes: cas.Attributes(r),
	}

	html := new(bytes.Buffer)
	if err := tmpl.Execute(html, binding); err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, error_500, err)
		return
	}

	html.WriteTo(w)
}

const index_html = `<!DOCTYPE html>
<html>
  <head>
    <title>Welcome {{.Username}}</title>
  </head>
  <body>
    <h1>Welcome {{.Username}} <a href="/logout">Logout</a></h1>
    <p>Your attributes are:</p>
    <ul>{{range $key, $values := .Attributes}}
      <li>{{$len := len $values}}{{$key}}:{{if gt $len 1}}
        <ul>{{range $values}}
          <li>{{.}}</li>{{end}}
        </ul>
      {{else}} {{index $values 0}}{{end}}</li>{{end}}
    </ul>
  </body>
</html>
`

const error_500 = `<!DOCTYPE html>
<html>
  <head>
    <title>Error 500</title>
  </head>
  <body>
    <h1>Error 500</h1>
    <p>%v</p>
  </body>
</html>
`
Output:

Index

Examples

Constants

View Source
const (
	INVALID_REQUEST            = "INVALID_REQUEST"
	INVALID_TICKET_SPEC        = "INVALID_TICKET_SPEC"
	UNAUTHORIZED_SERVICE       = "UNAUTHORIZED_SERVICE"
	UNAUTHORIZED_SERVICE_PROXY = "UNAUTHORIZED_SERVICE_PROXY"
	INVALID_PROXY_CALLBACK     = "INVALID_PROXY_CALLBACK"
	INVALID_TICKET             = "INVALID_TICKET"
	INVALID_SERVICE            = "INVALID_SERVICE"
	INTERNAL_ERROR             = "INTERNAL_ERROR"
)

AuthenticationError Code values

Variables

View Source
var (
	// Given Ticket is not associated with an AuthenticationResponse
	ErrInvalidTicket = errors.New("cas: ticket store: invalid ticket")
)

TicketStore errors

Functions

func AuthenticationDate

func AuthenticationDate(r *http.Request) time.Time

AuthenticationDate returns the date and time that authentication was performed.

This may return time.IsZero if Authentication Date information is not included in the CAS service validation response. This will be the case for CAS 2.0 protocol servers.

func IsAuthenticated

func IsAuthenticated(r *http.Request) bool

IsAuthenticated indicates whether the request has been authenticated with CAS.

Example
u, _ := url.Parse("https://cas.example.com")
c := cas.NewClient(&cas.Options{
	URL: u,
})

h := c.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
	if !cas.IsAuthenticated(r) {
		cas.RedirectToLogout(w, r)
	}

	fmt.Fprintf(w, "Hello World\n")
})

err := http.ListenAndServe(":8080", h)
if err != nil {
	log.Fatal("ListenAndServe: ", err)
}
Output:

func IsNewLogin

func IsNewLogin(r *http.Request) bool

IsNewLogin indicates whether the CAS service ticket was granted following a new authentication.

This may incorrectly return false if Is New Login information is not included in the CAS service validation response. This will be the case for CAS 2.0 protocol servers.

func IsRememberedLogin

func IsRememberedLogin(r *http.Request) bool

IsRememberedLogin indicates whether the CAS service ticket was granted by the presence of a long term authentication token.

This may incorrectly return false if Remembered Login information is not included in the CAS service validation response. This will be the case for CAS 2.0 protocol servers.

func MemberOf

func MemberOf(r *http.Request) []string

MemberOf returns the list of groups which the user belongs to.

func RedirectToLogin

func RedirectToLogin(w http.ResponseWriter, r *http.Request)

RedirectToLogin allows CAS protected handlers to redirect a request to the CAS login page.

Example
u, _ := url.Parse("https://cas.example.com")
c := cas.NewClient(&cas.Options{
	URL: u,
})

h := c.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
	cas.RedirectToLogin(w, r)
})

err := http.ListenAndServe(":8080", h)
if err != nil {
	log.Fatal("ListenAndServe: ", err)
}
Output:

func RedirectToLogout

func RedirectToLogout(w http.ResponseWriter, r *http.Request)

RedirectToLogout allows CAS protected handlers to redirect a request to the CAS logout page.

Example
u, _ := url.Parse("https://cas.example.com")
c := cas.NewClient(&cas.Options{
	URL: u,
})

h := c.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
	cas.RedirectToLogout(w, r)
})

err := http.ListenAndServe(":8080", h)
if err != nil {
	log.Fatal("ListenAndServe: ", err)
}
Output:

func Username

func Username(r *http.Request) string

Username returns the authenticated users username

Example
u, _ := url.Parse("https://cas.example.com")
c := cas.NewClient(&cas.Options{
	URL: u,
})

h := c.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
	if !cas.IsAuthenticated(r) {
		cas.RedirectToLogout(w, r)
	}

	fmt.Fprintf(w, "Hello %s\n", cas.Username(r))
})

err := http.ListenAndServe(":8080", h)
if err != nil {
	log.Fatal("ListenAndServe: ", err)
}
Output:

Types

type AuthenticationError

type AuthenticationError struct {
	Code    string
	Message string
}

AuthenticationError represents a CAS AuthenticationFailure response

func (AuthenticationError) AuthenticationError

func (e AuthenticationError) AuthenticationError() bool

AuthenticationError provides a differentiator for casting.

func (AuthenticationError) Error

func (e AuthenticationError) Error() string

Error returns the AuthenticationError as a string

type AuthenticationResponse

type AuthenticationResponse struct {
	User                string         // Users login name
	ProxyGrantingTicket string         // Proxy Granting Ticket
	Proxies             []string       // List of proxies
	AuthenticationDate  time.Time      // Time at which authentication was performed
	IsNewLogin          bool           // Whether new authentication was used to grant the service ticket
	IsRememberedLogin   bool           // Whether a long term token was used to grant the service ticket
	MemberOf            []string       // List of groups which the user is a member of
	Attributes          UserAttributes // Additional information about the user
}

AuthenticationResponse captures authenticated user information

func ParseServiceResponse

func ParseServiceResponse(data []byte) (*AuthenticationResponse, error)

ParseServiceResponse returns a successful response or an error

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client implements the main protocol

func NewClient

func NewClient(options *Options) *Client

NewClient creates a Client with the provided Options.

func (*Client) Handle

func (c *Client) Handle(h http.Handler) http.Handler

Handle wraps a http.Handler to provide CAS authentication for the handler.

func (*Client) HandleFunc

func (c *Client) HandleFunc(h func(http.ResponseWriter, *http.Request)) http.Handler

HandleFunc wraps a function to provide CAS authentication for the handler function.

func (*Client) LoginUrlForRequest

func (c *Client) LoginUrlForRequest(r *http.Request) (string, error)

LoginUrlForRequest determines the CAS login URL for the http.Request.

func (*Client) LogoutUrlForRequest

func (c *Client) LogoutUrlForRequest(r *http.Request) (string, error)

LogoutUrlForRequest determines the CAS logout URL for the http.Request.

func (*Client) RedirectToLogin

func (c *Client) RedirectToLogin(w http.ResponseWriter, r *http.Request)

RedirectToLogout replies to the request with a redirect URL to authenticate with CAS.

func (*Client) RedirectToLogout

func (c *Client) RedirectToLogout(w http.ResponseWriter, r *http.Request)

RedirectToLogout replies to the request with a redirect URL to log out of CAS.

func (*Client) ServiceValidateUrlForRequest

func (c *Client) ServiceValidateUrlForRequest(ticket string, r *http.Request) (string, error)

ServiceValidateUrlForRequest determines the CAS serviceValidate URL for the ticket and http.Request.

func (*Client) ValidateUrlForRequest

func (c *Client) ValidateUrlForRequest(ticket string, r *http.Request) (string, error)

ValidateUrlForRequest determines the CAS validate URL for the ticket and http.Request.

type MemoryStore

type MemoryStore struct {
	// contains filtered or unexported fields
}

MemoryStore implements the TicketStore interface storing ticket data in memory.

func (*MemoryStore) Clear

func (s *MemoryStore) Clear() error

Clear removes all ticket data

func (*MemoryStore) Delete

func (s *MemoryStore) Delete(id string) error

Delete removes the AuthenticationResponse for a ticket

func (*MemoryStore) Read

Read returns the AuthenticationResponse for a ticket

func (*MemoryStore) Write

func (s *MemoryStore) Write(id string, ticket *AuthenticationResponse) error

Write stores the AuthenticationResponse for a ticket

type Options

type Options struct {
	URL         *url.URL     // URL to the CAS service
	Store       TicketStore  // Custom TicketStore, if nil a MemoryStore will be used
	Client      *http.Client // Custom http client to allow options for http connections
	SendService bool         // Custom sendService to determine whether you need to send service param
}

Client configuration options

type TicketStore

type TicketStore interface {
	// Read returns the AuthenticationResponse data associated with a ticket identifier.
	Read(id string) (*AuthenticationResponse, error)

	// Write stores the AuthenticationResponse data received from a ticket validation.
	Write(id string, ticket *AuthenticationResponse) error

	// Delete removes the AuthenticationResponse data associated with a ticket identifier.
	Delete(id string) error

	// Clear removes all of the AuthenticationResponse data from the store.
	Clear() error
}

TicketStore provides an interface for storing and retrieving service ticket data.

type UserAttributes

type UserAttributes map[string][]string

UserAttributes represents additional data about the user

func Attributes

func Attributes(r *http.Request) UserAttributes

Attributes returns the authenticated users attributes.

func (UserAttributes) Add

func (a UserAttributes) Add(name, value string)

Add appends a new attribute.

func (UserAttributes) Get

func (a UserAttributes) Get(name string) string

Get retrieves an attribute by name.

Attributes are stored in arrays. Get will only return the first element.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL