/
app_session_token.go
99 lines (86 loc) · 2.8 KB
/
app_session_token.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package oauth
import (
"errors"
"net/http"
"time"
"github.com/authgear/authgear-server/pkg/api"
"github.com/authgear/authgear-server/pkg/api/apierrors"
"github.com/authgear/authgear-server/pkg/lib/infra/db/appdb"
"github.com/authgear/authgear-server/pkg/lib/oauth"
"github.com/authgear/authgear-server/pkg/lib/oauth/handler"
"github.com/authgear/authgear-server/pkg/lib/oauth/protocol"
"github.com/authgear/authgear-server/pkg/util/httproute"
"github.com/authgear/authgear-server/pkg/util/httputil"
"github.com/authgear/authgear-server/pkg/util/validation"
)
func ConfigureAppSessionTokenRoute(route httproute.Route) httproute.Route {
return route.
WithMethods("OPTIONS", "POST").
WithPathPattern("/oauth2/app_session_token")
}
var AppSessionTokenAPIRequestSchema = validation.NewSimpleSchema(`
{
"type": "object",
"additionalProperties": false,
"properties": {
"refresh_token": { "type": "string" }
},
"required": ["refresh_token"]
}
`)
var AppSessionTokenAPIResponseSchema = validation.NewSimpleSchema(`
{
"type": "object",
"properties": {
"app_session_token": { "type": "string" },
"expire_at": { "type": "string" }
},
"required": ["app_session_token", "expire_at"]
}
`)
type AppSessionTokenRequest struct {
RefreshToken string `json:"refresh_token"`
}
type AppSessionTokenResponse struct {
AppSessionToken string `json:"app_session_token"`
ExpireAt time.Time `json:"expire_at"`
}
type AppSessionTokenIssuer interface {
IssueAppSessionToken(refreshToken string) (string, *oauth.AppSessionToken, error)
}
type AppSessionTokenHandler struct {
Database *appdb.Handle
JSON JSONResponseWriter
AppSessionTokens AppSessionTokenIssuer
}
func (h *AppSessionTokenHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
var result *AppSessionTokenResponse
err := h.Database.WithTx(func() (err error) {
result, err = h.Handle(resp, req)
return err
})
if err == nil {
h.JSON.WriteResponse(resp, &api.Response{Result: result})
} else {
h.JSON.WriteResponse(resp, &api.Response{Error: err})
}
}
func (h *AppSessionTokenHandler) Handle(resp http.ResponseWriter, req *http.Request) (*AppSessionTokenResponse, error) {
var payload AppSessionTokenRequest
if err := httputil.BindJSONBody(req, resp, AppSessionTokenAPIRequestSchema.Validator(), &payload); err != nil {
return nil, err
}
token, sToken, err := h.AppSessionTokens.IssueAppSessionToken(payload.RefreshToken)
var oauthError *protocol.OAuthProtocolError
if errors.Is(err, handler.ErrInvalidRefreshToken) {
return nil, InvalidGrant.New(err.Error())
} else if errors.As(err, &oauthError) {
return nil, apierrors.NewForbidden(oauthError.Error())
} else if err != nil {
return nil, err
}
return &AppSessionTokenResponse{
AppSessionToken: token,
ExpireAt: sToken.ExpireAt,
}, nil
}