oauth2/server/token.go

140 lines
2.9 KiB
Go

package server
import (
"fmt"
"net/http"
"net/url"
"somehole.com/common/oauth2/session"
)
const TokenEndpoint = "/token"
type TokenError uint32
const (
TokenOk TokenError = iota
TokenErrorUnimplemented
TokenErrorUnauthorized
TokenErrorServerError
TokenErrorSlowDown
TokenErrorPending
)
func (te TokenError) Ok() bool {
return te == TokenOk
}
func (te TokenError) HttpStatus() (code int) {
switch te {
case TokenOk:
code = http.StatusOK
case TokenErrorUnimplemented:
code = http.StatusInternalServerError
case TokenErrorUnauthorized:
code = http.StatusUnauthorized
case TokenErrorServerError:
code = http.StatusInternalServerError
case TokenErrorSlowDown:
code = http.StatusBadRequest
case TokenErrorPending:
code = http.StatusBadRequest
default:
code = http.StatusInternalServerError
}
return
}
func (te TokenError) String() (out string) {
switch te {
case TokenOk:
out = "authenticated"
case TokenErrorUnimplemented:
out = "token server unimplemented"
case TokenErrorUnauthorized:
out = "user unauthorized"
case TokenErrorServerError:
out = "internal server error"
case TokenErrorSlowDown:
out = "slow down"
case TokenErrorPending:
out = "authorization pending"
default:
out = "unhandled error"
}
return
}
func (te TokenError) ErrorResponse() []byte {
var msg string
switch te {
case TokenErrorSlowDown:
msg = "slow_down"
case TokenErrorPending:
msg = "authorization_pending"
default:
msg = "internal_server_error"
}
return mustMarshalJson(struct {
Error string `json:"error"`
}{
Error: msg,
})
}
type TokenRequest struct {
ResponseType string
ClientId string
Code session.Code
}
func (tr TokenRequest) Request() Request {
return &tr
}
func (tr *TokenRequest) Parse(data *url.Values) (err error) {
if !data.Has("ClientId") {
err = fmt.Errorf("missing required client_id paramater")
return
}
tr.ClientId = data.Get("client_id")
if data.Has("code") {
tr.Code = session.Code(data.Get("code"))
}
if data.Has("response_type") {
tr.ResponseType = data.Get("response_type")
}
return
}
type TokenResponse struct {
Status int `json:"-"`
VerificationUri string `json:"verification_uri"`
UserCode session.Code `json:"user_code"`
DeviceCode session.Code `json:"device_code"`
Interval int `json:"interval"`
ExpiresIn int `json:"expires_in"`
}
func (tr *TokenResponse) HttpStatus() (code int) {
return tr.Status
}
func (tr *TokenResponse) Response() []byte {
return mustMarshalJson(tr)
}
type UnimplementedTokenServer struct{}
func (u UnimplementedTokenServer) mustEmbedUnimplementedTokenServer() {}
func (u UnimplementedTokenServer) Token(req *TokenRequest) (res *TokenResponse, errRes ErrorResponse) {
errRes = TokenErrorUnimplemented
return
}
type TokenServer interface {
mustEmbedUnimplementedTokenServer()
Token(*TokenRequest) (*TokenResponse, ErrorResponse)
}