mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 02:04:11 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			88 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
		
			Vendored
		
	
	
	
package openid
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"flag"
 | 
						|
	"fmt"
 | 
						|
	"sync"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
var maxNonceAge = flag.Duration("openid-max-nonce-age",
 | 
						|
	60*time.Second,
 | 
						|
	"Maximum accepted age for openid nonces. The bigger, the more"+
 | 
						|
		"memory is needed to store used nonces.")
 | 
						|
 | 
						|
type NonceStore interface {
 | 
						|
	// Returns nil if accepted, an error otherwise.
 | 
						|
	Accept(endpoint, nonce string) error
 | 
						|
}
 | 
						|
 | 
						|
type Nonce struct {
 | 
						|
	T time.Time
 | 
						|
	S string
 | 
						|
}
 | 
						|
 | 
						|
type SimpleNonceStore struct {
 | 
						|
	store map[string][]*Nonce
 | 
						|
	mutex *sync.Mutex
 | 
						|
}
 | 
						|
 | 
						|
func NewSimpleNonceStore() *SimpleNonceStore {
 | 
						|
	return &SimpleNonceStore{store: map[string][]*Nonce{}, mutex: &sync.Mutex{}}
 | 
						|
}
 | 
						|
 | 
						|
func (d *SimpleNonceStore) Accept(endpoint, nonce string) error {
 | 
						|
	// Value: A string 255 characters or less in length, that MUST be
 | 
						|
	// unique to this particular successful authentication response.
 | 
						|
	if len(nonce) < 20 || len(nonce) > 256 {
 | 
						|
		return errors.New("Invalid nonce")
 | 
						|
	}
 | 
						|
 | 
						|
	// The nonce MUST start with the current time on the server, and MAY
 | 
						|
	// contain additional ASCII characters in the range 33-126 inclusive
 | 
						|
	// (printable non-whitespace characters), as necessary to make each
 | 
						|
	// response unique. The date and time MUST be formatted as specified in
 | 
						|
	// section 5.6 of [RFC3339], with the following restrictions:
 | 
						|
 | 
						|
	// All times must be in the UTC timezone, indicated with a "Z".  No
 | 
						|
	// fractional seconds are allowed For example:
 | 
						|
	// 2005-05-15T17:11:51ZUNIQUE
 | 
						|
	ts, err := time.Parse(time.RFC3339, nonce[0:20])
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	now := time.Now()
 | 
						|
	diff := now.Sub(ts)
 | 
						|
	if diff > *maxNonceAge {
 | 
						|
		return fmt.Errorf("Nonce too old: %.2fs", diff.Seconds())
 | 
						|
	}
 | 
						|
 | 
						|
	s := nonce[20:]
 | 
						|
 | 
						|
	// Meh.. now we have to use a mutex, to protect that map from
 | 
						|
	// concurrent access. Could put a go routine in charge of it
 | 
						|
	// though.
 | 
						|
	d.mutex.Lock()
 | 
						|
	defer d.mutex.Unlock()
 | 
						|
 | 
						|
	if nonces, hasOp := d.store[endpoint]; hasOp {
 | 
						|
		// Delete old nonces while we are at it.
 | 
						|
		newNonces := []*Nonce{{ts, s}}
 | 
						|
		for _, n := range nonces {
 | 
						|
			if n.T == ts && n.S == s {
 | 
						|
				// If return early, just ignore the filtered list
 | 
						|
				// we have been building so far...
 | 
						|
				return errors.New("Nonce already used")
 | 
						|
			}
 | 
						|
			if now.Sub(n.T) < *maxNonceAge {
 | 
						|
				newNonces = append(newNonces, n)
 | 
						|
			}
 | 
						|
		}
 | 
						|
		d.store[endpoint] = newNonces
 | 
						|
	} else {
 | 
						|
		d.store[endpoint] = []*Nonce{{ts, s}}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 |