@@ 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)
+}