tiny 88x31 lexicon for atproto
at main 196 lines 5.1 kB view raw
1package db 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "strings" 8 9 "github.com/bluesky-social/indigo/atproto/auth/oauth" 10 "github.com/bluesky-social/indigo/atproto/syntax" 11) 12 13func (s Store) GetSession(ctx context.Context, did syntax.DID, sessionID string) (*oauth.ClientSessionData, error) { 14 row := s.pool.QueryRow(ctx, ` 15 SELECT 16 host_url, 17 authserver_url, 18 authserver_token_endpoint, 19 scopes, 20 access_token, 21 refresh_token, 22 dpop_authserver_nonce, 23 dpop_host_nonce, 24 dpop_privatekey_multibase 25 FROM sessions 26 WHERE account_did = $1 AND session_id = $2`, did.String(), sessionID) 27 var scope string 28 var csd oauth.ClientSessionData 29 csd.AccountDID = did 30 csd.SessionID = sessionID 31 err := row.Scan(&csd.HostURL, 32 &csd.AuthServerURL, 33 &csd.AuthServerTokenEndpoint, 34 &scope, 35 &csd.AccessToken, 36 &csd.RefreshToken, 37 &csd.DPoPAuthServerNonce, 38 &csd.DPoPHostNonce, 39 &csd.DPoPPrivateKeyMultibase, 40 ) 41 if err != nil { 42 return nil, errors.New("error scanning: " + err.Error()) 43 } 44 scopes := strings.Fields(scope) 45 csd.Scopes = scopes 46 return &csd, nil 47} 48 49func (s Store) SaveSession(ctx context.Context, sess oauth.ClientSessionData) error { 50 scope := strings.Join(sess.Scopes, " ") 51 _, err := s.pool.Exec(ctx, ` 52 INSERT INTO sessions ( 53 session_id, 54 account_did, 55 host_url, 56 authserver_url, 57 authserver_token_endpoint, 58 scopes, 59 access_token, 60 refresh_token, 61 dpop_authserver_nonce, 62 dpop_host_nonce, 63 dpop_privatekey_multibase 64 ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) 65 ON CONFLICT (session_id) 66 DO UPDATE SET 67 account_did = EXCLUDED.account_did, 68 host_url = EXCLUDED.host_url, 69 authserver_url = EXCLUDED.authserver_url, 70 authserver_token_endpoint = EXCLUDED.authserver_token_endpoint, 71 scopes = EXCLUDED.scopes, 72 access_token = EXCLUDED.access_token, 73 refresh_token = EXCLUDED.refresh_token, 74 dpop_authserver_nonce = EXCLUDED.dpop_authserver_nonce, 75 dpop_host_nonce = EXCLUDED.dpop_host_nonce, 76 dpop_privatekey_multibase = EXCLUDED.dpop_privatekey_multibase 77 `, 78 sess.SessionID, 79 sess.AccountDID.String(), 80 sess.HostURL, 81 sess.AuthServerURL, 82 sess.AuthServerTokenEndpoint, 83 scope, 84 sess.AccessToken, 85 sess.RefreshToken, 86 sess.DPoPAuthServerNonce, 87 sess.DPoPHostNonce, 88 sess.DPoPPrivateKeyMultibase, 89 ) 90 if err != nil { 91 return errors.New("failed to insert: " + err.Error()) 92 } 93 return nil 94} 95 96func (s Store) DeleteSession(ctx context.Context, did syntax.DID, sessionID string) error { 97 _, err := s.pool.Exec(ctx, `DELETE FROM sessions WHERE account_did = $1 AND session_id = $2`, did.String(), sessionID) 98 if err != nil { 99 return errors.New("failed to delete: " + err.Error()) 100 } 101 return nil 102} 103 104func (s Store) DeleteAllSessions(ctx context.Context, did string) error { 105 _, err := s.pool.Exec(ctx, `DELETE FROM sessions WHERE account_did = $1`, did) 106 return err 107} 108 109func (s Store) GetAuthRequestInfo(ctx context.Context, state string) (*oauth.AuthRequestData, error) { 110 row := s.pool.QueryRow(ctx, ` 111 SELECT 112 authserver_url, 113 account_did, 114 scopes, 115 request_uri, 116 authserver_token_endpoint, 117 pkce_verifier, 118 dpop_authserver_nonce, 119 dpop_privatekey_multibase 120 FROM requests 121 WHERE state = $1 122 `, state) 123 var ari oauth.AuthRequestData 124 ari.State = state 125 var did string 126 var scope string 127 err := row.Scan( 128 &ari.AuthServerURL, 129 &did, 130 &scope, 131 &ari.RequestURI, 132 &ari.AuthServerTokenEndpoint, 133 &ari.PKCEVerifier, 134 &ari.DPoPAuthServerNonce, 135 &ari.DPoPPrivateKeyMultibase, 136 ) 137 if err != nil { 138 return nil, errors.New("failed to scan: " + err.Error()) 139 } 140 scopes := strings.Fields(scope) 141 ari.Scopes = scopes 142 sdid, err := syntax.ParseDID(did) 143 if err != nil { 144 return nil, errors.New("failed to parse did: " + err.Error()) 145 } 146 ari.AccountDID = &sdid 147 return &ari, nil 148} 149 150func (s Store) SaveAuthRequestInfo(ctx context.Context, info oauth.AuthRequestData) error { 151 scope := strings.Join(info.Scopes, " ") 152 _, err := s.pool.Exec(ctx, ` 153 INSERT INTO requests ( 154 state, 155 authserver_url, 156 account_did, 157 scopes, 158 request_uri, 159 authserver_token_endpoint, 160 pkce_verifier, 161 dpop_authserver_nonce, 162 dpop_privatekey_multibase) 163 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`, 164 info.State, 165 info.AuthServerURL, 166 info.AccountDID, 167 scope, 168 info.RequestURI, 169 info.AuthServerTokenEndpoint, 170 info.PKCEVerifier, 171 info.DPoPAuthServerNonce, 172 info.DPoPPrivateKeyMultibase, 173 ) 174 if err != nil { 175 return errors.New("failed to insert: " + err.Error()) 176 } 177 return nil 178} 179 180func (s Store) DeleteAuthRequestInfo(ctx context.Context, state string) error { 181 _, err := s.pool.Exec(ctx, `DELETE FROM requests WHERE state = $1`, state) 182 if err != nil { 183 return errors.New("failed to delete: " + err.Error()) 184 } 185 return nil 186} 187 188func (s *Store) SetDpopPdsNonce(id int, dpopnonce string) error { 189 _, err := s.pool.Exec(context.Background(), ` 190 UPDATE oauthsessions SET dpop_pds_nonce = $1 WHERE id = $2 191 `, dpopnonce, id) 192 if err != nil { 193 return errors.New(fmt.Sprintf("error updating dpop nonce for id %d: %s", id, err.Error())) 194 } 195 return nil 196}