cas

package module
v2.2.2 Latest Latest
Warning

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

Go to latest
Published: Mar 2, 2021 License: MIT Imports: 15 Imported by: 42

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"

If you are using go modules, get the library by running:

go get gopkg.in/cas.v2@v2.2.1

Examples and Documentation

Documentation is available at: https://pkg.go.dev/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"
)

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 := NewClient(&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 UserAttributes
}

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

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

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

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

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

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

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

	html.WriteTo(w)
}

const indexHTML = `<!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 error500 = `<!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 := NewClient(&Options{
	URL: u,
})

h := c.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
	if !IsAuthenticated(r) {
		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 := NewClient(&Options{
	URL: u,
})

h := c.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
	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 := NewClient(&Options{
	URL: u,
})

h := c.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
	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 := NewClient(&Options{
	URL: u,
})

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

	fmt.Fprintf(w, "Hello %s\n", 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 added in v2.1.0

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

Handler returns a standard http.HandlerFunc, which will check the authenticated status (redirect user go login if needed) If the user pass the authenticated check, it will call the h's ServeHTTP method

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)

RedirectToLogin 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 DefaultURLScheme added in v2.2.0

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 added in v2.2.0

func NewDefaultURLScheme(base *url.URL) *DefaultURLScheme

NewDefaultURLScheme creates a URLScheme which uses the cas default urls

func (*DefaultURLScheme) Login added in v2.2.0

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

Login returns the url for the cas login page

func (*DefaultURLScheme) Logout added in v2.2.0

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

Logout returns the url for the cas logut page

func (*DefaultURLScheme) RestGrantingTicket added in v2.2.0

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

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

func (*DefaultURLScheme) RestLogout added in v2.2.0

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

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

func (*DefaultURLScheme) RestServiceTicket added in v2.2.0

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

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

func (*DefaultURLScheme) ServiceValidate added in v2.2.0

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

ServiceValidate returns the url for the service validation endpoint

func (*DefaultURLScheme) Validate added in v2.2.0

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
	Cookie       *http.Cookie // http.Cookie options, uses Path, Domain, MaxAge, HttpOnly, & Secure
	SessionStore SessionStore
}

Options : Client configuration options

type RestClient added in v2.2.0

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

RestClient uses the rest protocol provided by cas

func NewRestClient added in v2.2.0

func NewRestClient(options *RestOptions) *RestClient

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

func (*RestClient) Handle added in v2.2.0

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 added in v2.2.0

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 added in v2.2.0

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

Logout destroys the given granting ticket

func (*RestClient) RequestGrantingTicket added in v2.2.0

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 added in v2.2.0

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

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

func (*RestClient) ValidateServiceTicket added in v2.2.0

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

ValidateServiceTicket validates the service ticket and returns an AuthenticationResponse

type RestOptions added in v2.2.0

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

RestOptions provide options for the RestClient

type ServiceTicket added in v2.2.0

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 added in v2.2.0

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

ServiceTicketValidator is responsible for the validation of a service ticket

func NewServiceTicketValidator added in v2.2.0

func NewServiceTicketValidator(client *http.Client, casURL *url.URL) *ServiceTicketValidator

NewServiceTicketValidator create a new *ServiceTicketValidator

func (*ServiceTicketValidator) ServiceValidateUrl added in v2.2.0

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 added in v2.2.0

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 added in v2.2.0

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 SessionStore added in v2.2.0

type SessionStore interface {
	// Get the ticket with the session id
	Get(sessionID string) (string, bool)

	// Set the session with a ticket
	Set(sessionID, ticket string) error

	// Delete the session
	Delete(sessionID string) error
}

SessionStore store the session's ticket SessionID is retrived from cookies

func NewMemorySessionStore added in v2.2.0

func NewMemorySessionStore() SessionStore

NewMemorySessionStore create a default SessionStore that uses memory

type TicketGrantingTicket added in v2.2.0

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 added in v2.2.0

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