Skip to content

Commit 3c1b8f6

Browse files
authored
Oauth2 (#28)
* Complete unit tests for Twitter2Strategy * Update README for OAuth 2.0 * Fix TS error on jest with satisfies keyword by switching to ts-jest
1 parent eda24c6 commit 3c1b8f6

File tree

10 files changed

+6719
-16256
lines changed

10 files changed

+6719
-16256
lines changed

README.md

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Remix Auth Twitter ![example branch parameter](https://github.com/na2hiro/remix-auth-twitter/actions/workflows/main.yml/badge.svg?branch=main)
22

3-
Remix Auth plugin for Twitter OAuth 1.0a.
3+
Remix Auth plugin for Twitter [OAuth 2.0](https://developer.twitter.com/en/docs/authentication/oauth-2-0/user-access-token) and [1.0a](https://developer.twitter.com/en/docs/authentication/oauth-1-0a/obtaining-user-access-tokens).
44

55
## Supported runtimes
66

@@ -24,35 +24,86 @@ npm install remix-auth-twitter remix-auth
2424

2525
### Prerequisites
2626

27-
* Your app is registered to Twitter and has consumer key and secret issued https://developer.twitter.com/en/docs/authentication/oauth-1-0a/api-key-and-secret
27+
* Your app is registered to Twitter and you have client ID and secret (OAuth 2.0) or [consumer key and secret (OAuth 1.0a)](https://developer.twitter.com/en/docs/authentication/oauth-1-0a/api-key-and-secret)
2828
* Your app has [remix-auth](https://github.com/sergiodxa/remix-auth) set up and `authenticator` is provided:
2929
```typescript
3030
// app/services/auth.server.ts
3131
export let authenticator = ...;
3232
```
33+
34+
### Tell the Authenticator to use the Twitter strategy (OAuth 2.0)
3335

34-
### Tell the Authenticator to use the Twitter strategy
36+
Note that profile is not passed to the verify function as it was done for 1.0a. You need to manually hit [/2/users/me](https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me) for example in order to retrieve user's id, screen name, etc. The example uses [`twitter-api-v2`](https://github.com/PLhery/node-twitter-api-v2) to do so.
3537

3638
```typescript jsx
3739
// app/services/auth.server.ts
3840
import { Authenticator } from "remix-auth";
3941
import { sessionStorage } from "~/services/session.server";
40-
import { TwitterStrategy } from 'remix-auth-twitter';
42+
import { Twitter2Strategy } from 'remix-auth-twitter';
43+
import TwitterApi from 'twitter-api-v2';
4144

4245
export let authenticator = new Authenticator<User>(sessionStorage);
4346

44-
const clientID = process.env.TWITTER_CONSUMER_KEY;
45-
const clientSecret = process.env.TWITTER_CONSUMER_SECRET;
47+
const clientID = process.env.TWITTER_CLIENT_ID;
48+
const clientSecret = process.env.TWITTER_CLIENT_SECRET;
4649
if (!clientID || !clientSecret) {
47-
throw new Error("TWITTER_CONSUMER_KEY and TWITTER_CONSUMER_SECRET must be provided");
50+
throw new Error("TWITTER_CLIENT_ID and TWITTER_CLIENT_SECRET must be provided");
4851
}
4952

5053
authenticator.use(
51-
new TwitterStrategy(
54+
new Twitter2Strategy(
5255
{
5356
clientID,
5457
clientSecret,
5558
callbackURL: "https://my-app/login/callback",
59+
// List of scopes you want to be granted. See
60+
scopes: ["users.read", "tweet.read", "tweet.write"]
61+
},
62+
// Define what to do when the user is authenticated
63+
async ({ accessToken }) => {
64+
// In this example I want to use Twitter as identity provider: so resolve identity from the token
65+
const userClient = new TwitterApi(token);
66+
67+
const result = await userClient.v2.me({
68+
"user.fields": ["profile_image_url"],
69+
});
70+
// should handle errors
71+
const {id, username} = result.data;
72+
73+
// Return a user object to store in sessionStorage.
74+
// You can also throw Error to reject the login
75+
return await registerUser(
76+
accessToken,
77+
id,
78+
username
79+
);
80+
}
81+
),
82+
)
83+
```
84+
85+
### Tell the Authenticator to use the Twitter strategy (OAuth 1.0a)
86+
87+
```typescript jsx
88+
// app/services/auth.server.ts
89+
import { Authenticator } from "remix-auth";
90+
import { sessionStorage } from "~/services/session.server";
91+
import { Twitter1Strategy } from 'remix-auth-twitter';
92+
93+
export let authenticator = new Authenticator<User>(sessionStorage);
94+
95+
const consumerKey = process.env.TWITTER_CONSUMER_KEY;
96+
const consumerSecret = process.env.TWITTER_CONSUMER_SECRET;
97+
if (!consumerKey || !consumerSecret) {
98+
throw new Error("TWITTER_CONSUMER_KEY and TWITTER_CONSUMER_SECRET must be provided");
99+
}
100+
101+
authenticator.use(
102+
new Twitter1Strategy(
103+
{
104+
consumerKey,
105+
consumerSecret,
106+
callbackURL: "https://my-app/login/callback",
56107
alwaysReauthorize: false // otherwise, ask for permission every time
57108
},
58109
// Define what to do when the user is authenticated

config/jest.config.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,8 @@ const config: Config.InitialOptions = {
99
collectCoverageFrom: ["<rootDir>/src/**/*.ts"],
1010
setupFilesAfterEnv: ["<rootDir>/config/jest/setup.ts"],
1111
testMatch: ["<rootDir>/test/**/*.test.ts"],
12-
transform: {
13-
"\\.[jt]sx?$": [
14-
"babel-jest",
15-
{ configFile: "./config/jest/babel.config.js" },
16-
],
17-
},
12+
preset: "ts-jest",
13+
testEnvironment: "node",
1814
};
1915

2016
export default config;

config/jest/babel.config.js

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)