~emersion/go-oauth2

af6df1071867c3bbb0d6e23b98be31e49f4349db — Simon Ser 8 months ago 2e0d6e2 server
Add server
1 files changed, 89 insertions(+), 0 deletions(-)

A server.go
A server.go => server.go +89 -0
@@ 0,0 1,89 @@
package oauth2

import (
	"context"
	"encoding/json"
	"net/http"
	"net/url"
	"strings"
)

type AuthorizationReq struct {
	ResponseType ResponseType
	ClientID     string
	RedirectURI  string

	AuthorizationOptions
}

type ExchangeCodeReq struct {
	Code string

	ClientID     string
	ClientSecret string
	RedirectURI  string
}

type Backend interface {
	Authorize(w http.ResponseWriter, r *http.Request, ar *AuthorizationReq)
	ExchangeCode(ctx context.Context, req *ExchangeCodeReq) (*TokenResp, error)
	Refresh(ctx context.Context, refreshToken string, options *RefreshTokenOptions) (*TokenResp, error)
	Revoke(ctx context.Context, token string) error
	Introspect(ctx context.Context, token string) (*IntrospectionResp, error)
}

type Server struct {
	metadata ServerMetadata
	backend  Backend
	mux      *http.ServeMux
}

func NewServer(metadata *ServerMetadata, backend Backend) (*Server, error) {
	srv := &Server{
		metadata: *metadata,
		backend:  backend,
		mux:      http.NewServeMux(),
	}
	handlers := []struct {
		endpoint string
		handler  http.HandlerFunc
	}{
		{metadata.AuthorizationEndpoint, srv.authorize},
	}
	for _, h := range handlers {
		u, err := url.Parse(h.endpoint)
		if err != nil {
			return nil, err
		}
		srv.mux.HandleFunc(u.Path, h.handler)
	}

	srv.mux.HandleFunc("/.well-known/oauth-authorization-server", srv.getMetadata)

	return srv, nil
}

func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	srv.mux.ServeHTTP(w, r)
}

func (srv *Server) getMetadata(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(&srv.metadata)
}

func (srv *Server) authorize(w http.ResponseWriter, r *http.Request) {
	var ar AuthorizationReq

	q := r.URL.Query()
	ar.ResponseType = ResponseType(q.Get("response_type"))
	ar.ClientID = q.Get("client_id")
	ar.RedirectURI = q.Get("redirect_uri")
	if scope := q.Get("scope"); scope != "" {
		ar.Scope = strings.Split(scope, " ")
	}
	ar.State = q.Get("state")
	// TODO: MaxAge, ACRValues

	srv.backend.Authorize(w, r, &ar)
}