cas

package module
v2.2.2+incompatible Latest Latest
Warning

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

Go to latest
Published: May 21, 2019 License: MIT Imports: 16 Imported by: 1

README

CAS Client library

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

import "gopkg.in/cas.v2"

Examples and Documentation

Documentation is available at: http://godoc.org/gopkg.in/cas.v2 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 IsFirstAuthenticatedRequest

func IsFirstAuthenticatedRequest(r *http.Request) bool

IsFirstAuthenticatedRequest returns true, for the first successful authenticated request of a session

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) Handler

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

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. TODO why is this function exposed?

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. TODO why is this function exposed?

type DefaultURLScheme

type DefaultURLScheme struct {
	LoginPath           string
	LogoutPath          string
	ValidatePath        string
	ServiceValidatePath string
	RestEndpoint        string
	// contains filtered or unexported fields
}

DefaultURLScheme is a configurable URLScheme. Use NewDefaultURLScheme to create DefaultURLScheme with the default cas urls.

func NewDefaultURLScheme

func NewDefaultURLScheme(base *url.URL) *DefaultURLScheme

NewDefaultURLScheme creates a URLScheme which uses the cas default urls

func (*DefaultURLScheme) Login

func (scheme *DefaultURLScheme) Login() (*url.URL, error)

Login returns the url for the cas login page

func (*DefaultURLScheme) Logout

func (scheme *DefaultURLScheme) Logout() (*url.URL, error)

Logout returns the url for the cas logut page

func (*DefaultURLScheme) RestGrantingTicket

func (scheme *DefaultURLScheme) RestGrantingTicket() (*url.URL, error)

RestGrantingTicket returns the url for requesting an granting ticket via rest api

func (*DefaultURLScheme) RestLogout

func (scheme *DefaultURLScheme) RestLogout(tgt string) (*url.URL, error)

RestLogout returns the url for destroying an granting ticket via rest api

func (*DefaultURLScheme) RestServiceTicket

func (scheme *DefaultURLScheme) RestServiceTicket(tgt string) (*url.URL, error)

RestServiceTicket returns the url for requesting an service ticket via rest api

func (*DefaultURLScheme) ServiceValidate

func (scheme *DefaultURLScheme) ServiceValidate() (*url.URL, error)

ServiceValidate returns the url for the service validation endpoint

func (*DefaultURLScheme) Validate

func (scheme *DefaultURLScheme) Validate() (*url.URL, error)

Validate returns the url for the request validation endpoint

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
	URLScheme   URLScheme    // Custom url scheme, can be used to modify the request urls for the client
}

Client configuration options

type RestAuthenticator

type RestAuthenticator interface {
	Handle(h http.Handler) http.Handler
	RequestGrantingTicket(username string, password string) (TicketGrantingTicket, error)
	RequestServiceTicket(tgt TicketGrantingTicket) (ServiceTicket, error)
	ValidateServiceTicket(st ServiceTicket) (*AuthenticationResponse, error)
	Logout(tgt TicketGrantingTicket) error
	ShallForwardUnauthenticatedRESTRequests() bool
}

RestAuthenticator handles the cas authentication via the rest protocol

type RestClient

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

RestClient uses the rest protocol provided by cas

func NewRestClient

func NewRestClient(options *RestOptions) *RestClient

NewRestClient creates a new client for the cas rest protocol with the provided options

func (*RestClient) Handle

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

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

func (*RestClient) HandleFunc

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

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

func (*RestClient) Logout

func (c *RestClient) Logout(tgt TicketGrantingTicket) error

Logout destroys the given granting ticket

func (*RestClient) RequestGrantingTicket

func (c *RestClient) RequestGrantingTicket(username string, password string) (TicketGrantingTicket, error)

RequestGrantingTicket returns a new TGT, if the username and password authentication was successful

func (*RestClient) RequestServiceTicket

func (c *RestClient) RequestServiceTicket(tgt TicketGrantingTicket) (ServiceTicket, error)

RequestServiceTicket requests a service ticket with the TGT for the configured service url

func (*RestClient) ShallForwardUnauthenticatedRESTRequests

func (c *RestClient) ShallForwardUnauthenticatedRESTRequests() bool

ShallForwardUnauthenticatedRESTRequests specifies if unauthenticated requests shall be forwarded

func (*RestClient) ValidateServiceTicket

func (c *RestClient) ValidateServiceTicket(st ServiceTicket) (*AuthenticationResponse, error)

ValidateServiceTicket validates the service ticket and returns an AuthenticationResponse

type RestOptions

type RestOptions struct {
	CasURL                             *url.URL
	ServiceURL                         *url.URL
	Client                             *http.Client
	URLScheme                          URLScheme
	ForwardUnauthenticatedRESTRequests bool
}

RestOptions provide options for the RestClient

type ServiceTicket

type ServiceTicket string

ServiceTicket stands for the access granted by the CAS server to an application for a specific user, also known as ST

type ServiceTicketValidator

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

ServiceTicketValidator is responsible for the validation of a service ticket

func NewServiceTicketValidator

func NewServiceTicketValidator(client *http.Client, urlScheme URLScheme) *ServiceTicketValidator

func (*ServiceTicketValidator) ServiceValidateUrl

func (validator *ServiceTicketValidator) ServiceValidateUrl(serviceUrl *url.URL, ticket string) (string, error)

ServiceValidateUrl creates the service validation url for the cas >= 2 protocol. TODO the function is only exposed, because of the clients ServiceValidateUrl function

func (*ServiceTicketValidator) ValidateTicket

func (validator *ServiceTicketValidator) ValidateTicket(serviceUrl *url.URL, ticket string) (*AuthenticationResponse, error)

ValidateTicket validates the service ticket for the given server. The method will try to use the service validate endpoint of the cas >= 2 protocol, if the service validate endpoint not available, the function will use the cas 1 validate endpoint.

func (*ServiceTicketValidator) ValidateUrl

func (validator *ServiceTicketValidator) ValidateUrl(serviceUrl *url.URL, ticket string) (string, error)

ValidateUrl creates the validation url for the cas >= 1 protocol. TODO the function is only exposed, because of the clients ValidateUrl function

type TicketGrantingTicket

type TicketGrantingTicket string

TicketGrantingTicket represents a SSO session for a user, also known as TGT

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 URLScheme

type URLScheme interface {
	Login() (*url.URL, error)
	Logout() (*url.URL, error)
	Validate() (*url.URL, error)
	ServiceValidate() (*url.URL, error)
	RestGrantingTicket() (*url.URL, error)
	RestServiceTicket(tgt string) (*url.URL, error)
	RestLogout(tgt string) (*url.URL, error)
}

URLScheme creates the url which are required to handle the cas protocol.

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