Skip to content

Commit 34d377a

Browse files
committed
feat: Feathers Cloud Auth basic integration
1 parent bb9cb2a commit 34d377a

File tree

9 files changed

+5168
-21789
lines changed

9 files changed

+5168
-21789
lines changed

feathers-chat-ts/config/default.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"public": "../public/",
55
"origins": [
66
"http://localhost:3030",
7-
"http://localhost:3000"
7+
"http://localhost:3001"
88
],
99
"paginate": {
1010
"default": 10,

feathers-chat-ts/package-lock.json

Lines changed: 88 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

feathers-chat-ts/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"migrate:make": "knex migrate:make"
4747
},
4848
"dependencies": {
49+
"@featherscloud/auth": "^0.6.5",
4950
"@feathersjs/adapter-commons": "^5.0.28",
5051
"@feathersjs/authentication": "^5.0.28",
5152
"@feathersjs/authentication-client": "^5.0.28",

feathers-chat-ts/src/authentication.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,74 @@
11
import type { Params } from '@feathersjs/feathers'
2-
import { AuthenticationService, JWTStrategy } from '@feathersjs/authentication'
2+
import { AuthenticationParams, AuthenticationRequest, AuthenticationService, JWTStrategy } from '@feathersjs/authentication'
3+
import { CloudAuthUser, createVerifier } from '@featherscloud/auth'
34
import { LocalStrategy } from '@feathersjs/authentication-local'
45
import { oauth, OAuthStrategy } from '@feathersjs/authentication-oauth'
56
import type { OAuthProfile } from '@feathersjs/authentication-oauth'
67
import type { Application } from './declarations'
8+
import { NotAuthenticated } from '@feathersjs/errors'
79

810
declare module './declarations' {
911
interface ServiceTypes {
1012
authentication: AuthenticationService
1113
}
1214
}
1315

16+
const verifier = createVerifier({
17+
appId: 'did:key:z6Mksc9d7DyrKFpyNcZHUy5G78vGFaFwdAuzJSBd9HHM9Msk',
18+
})
19+
20+
class CloudAuthStrategy extends JWTStrategy {
21+
async findUser (cloudUser: CloudAuthUser, params: AuthenticationParams) {
22+
const result = await this.entityService.find({
23+
...params,
24+
query: {
25+
email: cloudUser.email
26+
}
27+
})
28+
const [user] = Array.isArray(result) ? result : result.data;
29+
30+
if (!user) {
31+
return this.createUser(cloudUser, params);
32+
}
33+
34+
return user
35+
}
36+
37+
async createUser (user: CloudAuthUser, params: AuthenticationParams) {
38+
const entity = await this.entityService.create({
39+
email: user.email
40+
}, params);
41+
42+
return entity;
43+
}
44+
45+
async authenticate(authentication: AuthenticationRequest, params: AuthenticationParams) {
46+
const { accessToken } = authentication;
47+
const { entity } = this.configuration;
48+
if (!accessToken) {
49+
throw new NotAuthenticated('No access token');
50+
}
51+
const verified = await verifier.verify(accessToken);
52+
const result = {
53+
accessToken,
54+
authentication: {
55+
strategy: this.name || 'jwt',
56+
accessToken,
57+
...verified
58+
}
59+
};
60+
61+
if (entity === null || verified.user === null) {
62+
return result;
63+
}
64+
65+
return {
66+
...result,
67+
[entity]: await this.findUser(verified.user, params)
68+
};
69+
}
70+
}
71+
1472
class GitHubStrategy extends OAuthStrategy {
1573
async getEntityData(profile: OAuthProfile, existing: any, params: Params) {
1674
const baseData = await super.getEntityData(profile, existing, params)
@@ -28,7 +86,7 @@ class GitHubStrategy extends OAuthStrategy {
2886
export const authentication = (app: Application) => {
2987
const authentication = new AuthenticationService(app)
3088

31-
authentication.register('jwt', new JWTStrategy())
89+
authentication.register('jwt', new CloudAuthStrategy())
3290
authentication.register('local', new LocalStrategy())
3391
authentication.register('github', new GitHubStrategy())
3492

feathers-chat-ts/src/client.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// For more information about this file see https://dove.feathersjs.com/guides/cli/client.html
22
import { feathers } from '@feathersjs/feathers'
33
import type { TransportConnection, Application } from '@feathersjs/feathers'
4-
import authenticationClient from '@feathersjs/authentication-client'
4+
import authenticationClient, { AuthenticationClient } from '@feathersjs/authentication-client'
55
import type { AuthenticationClientOptions } from '@feathersjs/authentication-client'
66

77
import { messageClient } from './services/messages/messages.shared'
@@ -10,6 +10,8 @@ export type { Message, MessageData, MessageQuery, MessagePatch } from './service
1010
import { userClient } from './services/users/users.shared'
1111
export type { User, UserData, UserQuery, UserPatch } from './services/users/users.shared'
1212

13+
import { createClient as createAuthClient, LoginRequiredError } from '@featherscloud/auth'
14+
1315
export interface Configuration {
1416
connection: TransportConnection<ServiceTypes>
1517
}
@@ -18,6 +20,26 @@ export interface ServiceTypes {}
1820

1921
export type ClientApplication = Application<ServiceTypes, Configuration>
2022

23+
const auth = createAuthClient({
24+
appId: 'did:key:z6Mksc9d7DyrKFpyNcZHUy5G78vGFaFwdAuzJSBd9HHM9Msk',
25+
tokenUrl: 'http://localhost:8787/token',
26+
})
27+
28+
class CloudAuthClient extends AuthenticationClient {
29+
async getAccessToken() {
30+
try {
31+
const token = await auth.getAccessToken()
32+
return token
33+
} catch (error: unknown) {
34+
if (error instanceof LoginRequiredError) {
35+
window.location.href = await auth.getLoginUrl(error)
36+
}
37+
38+
throw error
39+
}
40+
}
41+
}
42+
2143
/**
2244
* Returns a typed client for the feathers-chat app.
2345
*
@@ -33,7 +55,10 @@ export const createClient = <Configuration = any>(
3355
const client: ClientApplication = feathers()
3456

3557
client.configure(connection)
36-
client.configure(authenticationClient(authenticationOptions))
58+
client.configure(authenticationClient({
59+
Authentication: CloudAuthClient,
60+
...authenticationOptions
61+
}))
3762
client.set('connection', connection)
3863

3964
client.configure(userClient)

0 commit comments

Comments
 (0)