digest

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2020 License: MIT Imports: 16 Imported by: 67

README

HTTP Digest Access Authentication

go.dev reference

This package provides a http.RoundTripper implementation which re-uses digest challenges

package main

import (
  "net/http"

  "github.com/icholy/digest"
)

func main() {
  client := &http.Client{
    Transport: &digest.Transport{
      Username: "foo",
      Password: "bar",
    },
  }
  res, err := client.Get("http://localhost:8080/some_outdated_service")
  if err != nil {
    panic(err)
  }
  defer res.Body.Close()
}

Low Level API

func main() {
  // get the challenge from a 401 response
  header := res.Header.Get("WWW-Authenticate")
  chal, _ := digest.ParseChallenge(header)

  // use it to create credentials for the next request
  cred, _ := digest.Digest(chal, digest.Options{
    Username: "foo",
    Password: "bar",
    Method:   req.Method,
    URI:      req.URL.RequestURI(),
    Count:    1,
  })
  req.Header.Set("Authorization", cred.String())

  // if you use the same challenge again, you must increment the Count
  cred2, _ := digest.Digest(chal, digest.Options{
    Username: "foo",
    Password: "bar",
    Method:   req2.Method,
    URI:      req2.URL.RequestURI(),
    Count:    2,
  })
  req2.Header.Set("Authorization", cred.String())
}

Documentation

Index

Examples

Constants

View Source
const Prefix = "Digest "

Prefix for digest authentication headers

Variables

This section is empty.

Functions

func CanDigest

func CanDigest(c *Challenge) bool

CanDigest checks if the algorithm and qop are supported

func IsDigest

func IsDigest(header string) bool

IsDigest returns true if the header value is a digest auth header

Types

type Challenge

type Challenge struct {
	Realm     string
	Domain    []string
	Nonce     string
	Opaque    string
	Stale     bool
	Algorithm string
	QOP       []string
	Charset   string
	Userhash  bool
}

Challenge is a challenge sent in the WWW-Authenticate header

func FindChallenge

func FindChallenge(h http.Header) (*Challenge, error)

FindChallenge returns the first supported challenge in the headers

func ParseChallenge

func ParseChallenge(s string) (*Challenge, error)

ParseChallenge parses the WWW-Authenticate header challenge

func (*Challenge) String

func (c *Challenge) String() string

String returns the foramtted header value

func (*Challenge) SupportsQOP

func (c *Challenge) SupportsQOP(qop string) bool

SupportsQOP returns true if the challenge advertises support for the provided qop value

type Credentials

type Credentials struct {
	Username  string
	Realm     string
	Nonce     string
	URI       string
	Response  string
	Algorithm string
	Cnonce    string
	Opaque    string
	QOP       string
	Nc        int
	Userhash  bool
}

Credentials is a parsed version of the Authorization header

func Digest

func Digest(c *Challenge, o Options) (*Credentials, error)

Digest creates credentials from a challenge and request options. Note: if you want to re-use a challenge, you must increment the Count.

Example
package main

import (
	"net/http"

	"github.com/icholy/digest"
)

func main() {
	// The first request will return a 401 Unauthorized response
	req, _ := http.NewRequest(http.MethodGet, "http://httpbin.org/digest-auth/auth/foo/bar/SHA-512", nil)
	res, _ := http.DefaultClient.Do(req)
	// Create digest credentials from the request challenge
	chal, _ := digest.FindChallenge(res.Header)
	cred, _ := digest.Digest(chal, digest.Options{
		Method:   req.Method,
		URI:      req.URL.RequestURI(),
		Username: "foo",
		Password: "bar",
	})
	// Try the request again with the credentials
	req.Header.Set("Authorization", cred.String())
	res, _ = http.DefaultClient.Do(req)
	println(res.Status)
}
Output:

func ParseCredentials

func ParseCredentials(s string) (*Credentials, error)

ParseCredentials parses the Authorization header value into credentials

func (*Credentials) String

func (c *Credentials) String() string

String formats the credentials into the header format

type Options

type Options struct {
	Method   string
	URI      string
	Count    int
	Username string
	Password string

	// used for testing
	Cnonce string
}

Options for creating a credentials

type Transport

type Transport struct {
	Username  string
	Password  string
	Transport http.RoundTripper
	// contains filtered or unexported fields
}

Transport implements http.RoundTripper

Example
package main

import (
	"net/http"

	"github.com/icholy/digest"
)

func main() {
	client := http.Client{
		Transport: &digest.Transport{
			Username: "foo",
			Password: "bar",
		},
	}
	res, _ := client.Get("http://httpbin.org/digest-auth/auth/foo/bar/SHA-512")
	println(res.Status)
}
Output:

func (*Transport) RoundTrip

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip will try to authorize the request using a cached challenge. If that doesn't work and we receive a 401, we'll try again using that challenge.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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