forked from tangled.org/core
this repo has no description
at master 5.4 kB view raw
1package auth 2 3import ( 4 "context" 5 "fmt" 6 "net/http" 7 "time" 8 9 comatproto "github.com/bluesky-social/indigo/api/atproto" 10 "github.com/bluesky-social/indigo/atproto/identity" 11 "github.com/bluesky-social/indigo/xrpc" 12 "github.com/gorilla/sessions" 13 "tangled.sh/tangled.sh/core/appview" 14) 15 16type Auth struct { 17 Store *sessions.CookieStore 18} 19 20type AtSessionCreate struct { 21 comatproto.ServerCreateSession_Output 22 PDSEndpoint string 23} 24 25type AtSessionRefresh struct { 26 comatproto.ServerRefreshSession_Output 27 PDSEndpoint string 28} 29 30func Make(secret string) (*Auth, error) { 31 store := sessions.NewCookieStore([]byte(secret)) 32 return &Auth{store}, nil 33} 34 35func (a *Auth) CreateInitialSession(ctx context.Context, resolved *identity.Identity, appPassword string) (*comatproto.ServerCreateSession_Output, error) { 36 37 pdsUrl := resolved.PDSEndpoint() 38 client := xrpc.Client{ 39 Host: pdsUrl, 40 } 41 42 atSession, err := comatproto.ServerCreateSession(ctx, &client, &comatproto.ServerCreateSession_Input{ 43 Identifier: resolved.DID.String(), 44 Password: appPassword, 45 }) 46 if err != nil { 47 return nil, fmt.Errorf("invalid app password") 48 } 49 50 return atSession, nil 51} 52 53// Sessionish is an interface that provides access to the common fields of both types. 54type Sessionish interface { 55 GetAccessJwt() string 56 GetActive() *bool 57 GetDid() string 58 GetDidDoc() *interface{} 59 GetHandle() string 60 GetRefreshJwt() string 61 GetStatus() *string 62} 63 64// Create a wrapper type for ServerRefreshSession_Output 65type RefreshSessionWrapper struct { 66 *comatproto.ServerRefreshSession_Output 67} 68 69func (s *RefreshSessionWrapper) GetAccessJwt() string { 70 return s.AccessJwt 71} 72 73func (s *RefreshSessionWrapper) GetActive() *bool { 74 return s.Active 75} 76 77func (s *RefreshSessionWrapper) GetDid() string { 78 return s.Did 79} 80 81func (s *RefreshSessionWrapper) GetDidDoc() *interface{} { 82 return s.DidDoc 83} 84 85func (s *RefreshSessionWrapper) GetHandle() string { 86 return s.Handle 87} 88 89func (s *RefreshSessionWrapper) GetRefreshJwt() string { 90 return s.RefreshJwt 91} 92 93func (s *RefreshSessionWrapper) GetStatus() *string { 94 return s.Status 95} 96 97// Create a wrapper type for ServerRefreshSession_Output 98type CreateSessionWrapper struct { 99 *comatproto.ServerCreateSession_Output 100} 101 102func (s *CreateSessionWrapper) GetAccessJwt() string { 103 return s.AccessJwt 104} 105 106func (s *CreateSessionWrapper) GetActive() *bool { 107 return s.Active 108} 109 110func (s *CreateSessionWrapper) GetDid() string { 111 return s.Did 112} 113 114func (s *CreateSessionWrapper) GetDidDoc() *interface{} { 115 return s.DidDoc 116} 117 118func (s *CreateSessionWrapper) GetHandle() string { 119 return s.Handle 120} 121 122func (s *CreateSessionWrapper) GetRefreshJwt() string { 123 return s.RefreshJwt 124} 125 126func (s *CreateSessionWrapper) GetStatus() *string { 127 return s.Status 128} 129 130func (a *Auth) ClearSession(r *http.Request, w http.ResponseWriter) error { 131 clientSession, err := a.Store.Get(r, appview.SessionName) 132 if err != nil { 133 return fmt.Errorf("invalid session", err) 134 } 135 if clientSession.IsNew { 136 return fmt.Errorf("invalid session") 137 } 138 clientSession.Options.MaxAge = -1 139 return clientSession.Save(r, w) 140} 141 142func (a *Auth) StoreSession(r *http.Request, w http.ResponseWriter, atSessionish Sessionish, pdsEndpoint string) error { 143 clientSession, _ := a.Store.Get(r, appview.SessionName) 144 clientSession.Values[appview.SessionHandle] = atSessionish.GetHandle() 145 clientSession.Values[appview.SessionDid] = atSessionish.GetDid() 146 clientSession.Values[appview.SessionPds] = pdsEndpoint 147 clientSession.Values[appview.SessionAccessJwt] = atSessionish.GetAccessJwt() 148 clientSession.Values[appview.SessionRefreshJwt] = atSessionish.GetRefreshJwt() 149 clientSession.Values[appview.SessionExpiry] = time.Now().Add(time.Minute * 15).Format(time.RFC3339) 150 clientSession.Values[appview.SessionAuthenticated] = true 151 return clientSession.Save(r, w) 152} 153 154func (a *Auth) AuthorizedClient(r *http.Request) (*xrpc.Client, error) { 155 clientSession, err := a.Store.Get(r, "appview-session") 156 if err != nil || clientSession.IsNew { 157 return nil, err 158 } 159 160 did := clientSession.Values["did"].(string) 161 pdsUrl := clientSession.Values["pds"].(string) 162 accessJwt := clientSession.Values["accessJwt"].(string) 163 refreshJwt := clientSession.Values["refreshJwt"].(string) 164 165 client := &xrpc.Client{ 166 Host: pdsUrl, 167 Auth: &xrpc.AuthInfo{ 168 AccessJwt: accessJwt, 169 RefreshJwt: refreshJwt, 170 Did: did, 171 }, 172 } 173 174 return client, nil 175} 176 177func (a *Auth) GetSession(r *http.Request) (*sessions.Session, error) { 178 return a.Store.Get(r, appview.SessionName) 179} 180 181func (a *Auth) GetDid(r *http.Request) string { 182 clientSession, err := a.Store.Get(r, appview.SessionName) 183 if err != nil || clientSession.IsNew { 184 return "" 185 } 186 187 return clientSession.Values[appview.SessionDid].(string) 188} 189 190func (a *Auth) GetHandle(r *http.Request) string { 191 clientSession, err := a.Store.Get(r, appview.SessionName) 192 if err != nil || clientSession.IsNew { 193 return "" 194 } 195 196 return clientSession.Values[appview.SessionHandle].(string) 197} 198 199type User struct { 200 Handle string 201 Did string 202 Pds string 203} 204 205func (a *Auth) GetUser(r *http.Request) *User { 206 clientSession, err := a.Store.Get(r, appview.SessionName) 207 208 if err != nil || clientSession.IsNew { 209 return nil 210 } 211 212 return &User{ 213 Handle: clientSession.Values[appview.SessionHandle].(string), 214 Did: clientSession.Values[appview.SessionDid].(string), 215 Pds: clientSession.Values[appview.SessionPds].(string), 216 } 217}