everything you need to create an atproto appview
at main 86 lines 2.5 kB view raw
1package oauth 2 3import ( 4 "fmt" 5 "net" 6 "net/http" 7 "time" 8 9 "github.com/bluesky-social/indigo/atproto/auth/oauth" 10 atpclient "github.com/bluesky-social/indigo/atproto/client" 11 atcrypto "github.com/bluesky-social/indigo/atproto/crypto" 12 "github.com/charmbracelet/log" 13 "github.com/gorilla/sessions" 14 "tangled.org/oppi.li/atproto-starterkit/appview/config" 15 "tangled.org/oppi.li/atproto-starterkit/idresolver" 16) 17 18type OAuth struct { 19 ClientApp *oauth.ClientApp 20 SessStore *sessions.CookieStore 21 Config *config.Config 22 IdResolver *idresolver.Resolver 23 Logger *log.Logger 24} 25 26func New(config *config.Config, res *idresolver.Resolver, logger *log.Logger) (*OAuth, error) { 27 var oauthConfig oauth.ClientConfig 28 var clientUri string 29 30 if config.Core.Dev { 31 clientUri = "http://" + net.JoinHostPort("127.0.0.1", config.Core.Port()) 32 callbackUri := clientUri + "/oauth/callback" 33 oauthConfig = oauth.NewLocalhostConfig(callbackUri, Scopes) 34 } else { 35 clientUri = config.Core.Host 36 clientId := fmt.Sprintf("%s/oauth/client-metadata.json", clientUri) 37 callbackUri := clientUri + "/oauth/callback" 38 oauthConfig = oauth.NewPublicConfig(clientId, callbackUri, Scopes) 39 } 40 41 // configure client secret 42 priv, err := atcrypto.ParsePrivateMultibase(config.OAuth.ClientSecret) 43 if err != nil { 44 return nil, err 45 } 46 if err := oauthConfig.SetClientSecret(priv, config.OAuth.ClientKid); err != nil { 47 return nil, err 48 } 49 50 authStore, err := NewRedisStore(&RedisStoreConfig{ 51 RedisURL: config.Redis.ToURL(), 52 SessionExpiryDuration: time.Hour * 24 * 90, 53 SessionInactivityDuration: time.Hour * 24 * 14, 54 AuthRequestExpiryDuration: time.Minute * 30, 55 }) 56 if err != nil { 57 return nil, err 58 } 59 60 sessStore := sessions.NewCookieStore([]byte(config.Core.CookieSecret)) 61 62 clientApp := oauth.NewClientApp(&oauthConfig, authStore) 63 clientApp.Dir = res.Directory() 64 65 // allow non-public transports in dev mode 66 if config.Core.Dev { 67 clientApp.Resolver.Client.Transport = http.DefaultTransport 68 } 69 70 logger.Info("oauth setup successfully", "confidential", clientApp.Config.IsConfidential()) 71 return &OAuth{ 72 ClientApp: clientApp, 73 Config: config, 74 SessStore: sessStore, 75 IdResolver: res, 76 Logger: logger, 77 }, nil 78} 79 80func (o *OAuth) AuthorizedClient(r *http.Request) (*atpclient.APIClient, error) { 81 session, err := o.ResumeSession(r) 82 if err != nil { 83 return nil, fmt.Errorf("error getting session: %w", err) 84 } 85 return session.APIClient(), nil 86}