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 { 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) 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) }