oauth2/server/token.go

130 lines
2.7 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
}
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"
}
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 {
State session.State
Code session.Code
}
func (tr *TokenRequest) Parse(data *url.Values) (err error) {
if !data.Has("code") {
err = fmt.Errorf("missing code paramater")
return
}
if !data.Has("state") {
err = fmt.Errorf("missing state parameter")
return
}
tr.State = session.State(data.Get("state"))
tr.Code = session.Code(data.Get("code"))
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 uint8 `json:"interval"`
}
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 *TokenError) {
te := TokenErrorUnimplemented
errRes = &te
return
}
type TokenServer interface {
mustEmbedUnimplementedTokenServer()
Token(*TokenRequest) (*TokenResponse, *TokenError)
}