mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
feat: New JWT in Every Authenticated Response
This commit is contained in:
parent
cae9de0f2b
commit
6811f45a1c
@ -4,6 +4,7 @@ import { AuthChecker } from 'type-graphql'
|
|||||||
import decode from '../jwt/decode'
|
import decode from '../jwt/decode'
|
||||||
import { apiGet } from '../apis/loginAPI'
|
import { apiGet } from '../apis/loginAPI'
|
||||||
import CONFIG from '../config'
|
import CONFIG from '../config'
|
||||||
|
import encode from '../jwt/encode'
|
||||||
|
|
||||||
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
|
||||||
export const isAuthorized: AuthChecker<any> = async ({ root, args, context, info }, roles) => {
|
export const isAuthorized: AuthChecker<any> = async ({ root, args, context, info }, roles) => {
|
||||||
@ -14,6 +15,7 @@ export const isAuthorized: AuthChecker<any> = async ({ root, args, context, info
|
|||||||
`${CONFIG.LOGIN_API_URL}checkSessionState?session_id=${decoded.sessionId}`,
|
`${CONFIG.LOGIN_API_URL}checkSessionState?session_id=${decoded.sessionId}`,
|
||||||
)
|
)
|
||||||
context.sessionId = decoded.sessionId
|
context.sessionId = decoded.sessionId
|
||||||
|
context.setHeaders.push({ key: 'token', value: encode(decoded.sessionId) })
|
||||||
return result.success
|
return result.success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
backend/src/graphql/models/LoginResponse.ts
Normal file
19
backend/src/graphql/models/LoginResponse.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
import { ObjectType, Field } from 'type-graphql'
|
||||||
|
import { User } from '../models/User'
|
||||||
|
import encode from '../../jwt/encode'
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class LoginResponse {
|
||||||
|
constructor(json: any) {
|
||||||
|
this.token = encode(json.sessionId)
|
||||||
|
this.user = new User(json.user)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
token: string
|
||||||
|
|
||||||
|
@Field(() => User)
|
||||||
|
user: User
|
||||||
|
}
|
||||||
@ -4,10 +4,10 @@
|
|||||||
import { Resolver, Query, Args, Arg, Authorized, Ctx } from 'type-graphql'
|
import { Resolver, Query, Args, Arg, Authorized, Ctx } from 'type-graphql'
|
||||||
import CONFIG from '../../config'
|
import CONFIG from '../../config'
|
||||||
import { CheckUsernameResponse } from '../models/CheckUsernameResponse'
|
import { CheckUsernameResponse } from '../models/CheckUsernameResponse'
|
||||||
import { User } from '../models/User'
|
|
||||||
import { LoginViaVerificationCode } from '../models/LoginViaVerificationCode'
|
import { LoginViaVerificationCode } from '../models/LoginViaVerificationCode'
|
||||||
import { SendPasswordResetEmailResponse } from '../models/SendPasswordResetEmailResponse'
|
import { SendPasswordResetEmailResponse } from '../models/SendPasswordResetEmailResponse'
|
||||||
import { UpdateUserInfosResponse } from '../models/UpdateUserInfosResponse'
|
import { UpdateUserInfosResponse } from '../models/UpdateUserInfosResponse'
|
||||||
|
import { LoginResponse } from '../models/LoginResponse'
|
||||||
import {
|
import {
|
||||||
ChangePasswordArgs,
|
ChangePasswordArgs,
|
||||||
CheckUsernameArgs,
|
CheckUsernameArgs,
|
||||||
@ -16,12 +16,11 @@ import {
|
|||||||
UpdateUserInfosArgs,
|
UpdateUserInfosArgs,
|
||||||
} from '../inputs/LoginUserInput'
|
} from '../inputs/LoginUserInput'
|
||||||
import { apiPost, apiGet } from '../../apis/loginAPI'
|
import { apiPost, apiGet } from '../../apis/loginAPI'
|
||||||
import encode from '../../jwt/encode'
|
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class UserResolver {
|
export class UserResolver {
|
||||||
@Query(() => String)
|
@Query(() => LoginResponse)
|
||||||
async login(@Args() { email, password }: UnsecureLoginArgs): Promise<string> {
|
async login(@Args() { email, password }: UnsecureLoginArgs): Promise<LoginResponse> {
|
||||||
email = email.trim().toLowerCase()
|
email = email.trim().toLowerCase()
|
||||||
const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password })
|
const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password })
|
||||||
|
|
||||||
@ -30,10 +29,7 @@ export class UserResolver {
|
|||||||
throw new Error(result.data)
|
throw new Error(result.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = result.data
|
return new LoginResponse({ sessionId: result.data.session_id, user: result.data.user })
|
||||||
const sessionId = data.session_id
|
|
||||||
delete data.session_id
|
|
||||||
return encode({ sessionId, user: new User(data.user) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => LoginViaVerificationCode)
|
@Query(() => LoginViaVerificationCode)
|
||||||
|
|||||||
@ -22,14 +22,15 @@ import { isAuthorized } from './auth/auth'
|
|||||||
|
|
||||||
const DB_VERSION = '0001-init_db'
|
const DB_VERSION = '0001-init_db'
|
||||||
|
|
||||||
const context = (req: any) => {
|
const context = (args: any) => {
|
||||||
const authorization = req.req.headers.authorization
|
const authorization = args.req.headers.authorization
|
||||||
let token = null
|
let token = null
|
||||||
if (authorization) {
|
if (authorization) {
|
||||||
token = req.req.headers.authorization.replace(/^Bearer /, '')
|
token = authorization.replace(/^Bearer /, '')
|
||||||
}
|
}
|
||||||
const context = {
|
const context = {
|
||||||
token,
|
token,
|
||||||
|
setHeaders: [],
|
||||||
}
|
}
|
||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
@ -61,8 +62,24 @@ async function main() {
|
|||||||
// Express Server
|
// Express Server
|
||||||
const server = express()
|
const server = express()
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
{
|
||||||
|
requestDidStart() {
|
||||||
|
return {
|
||||||
|
willSendResponse(requestContext: any) {
|
||||||
|
const { setHeaders = [] } = requestContext.context
|
||||||
|
setHeaders.forEach(({ key, value }: { [key: string]: string }) => {
|
||||||
|
requestContext.response.http.headers.append(key, value)
|
||||||
|
})
|
||||||
|
return requestContext
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
// Apollo Server
|
// Apollo Server
|
||||||
const apollo = new ApolloServer({ schema, playground, context })
|
const apollo = new ApolloServer({ schema, playground, context, plugins })
|
||||||
apollo.applyMiddleware({ app: server })
|
apollo.applyMiddleware({ app: server })
|
||||||
|
|
||||||
// Start Server
|
// Start Server
|
||||||
|
|||||||
@ -5,13 +5,9 @@ import jwt from 'jsonwebtoken'
|
|||||||
import CONFIG from '../config/'
|
import CONFIG from '../config/'
|
||||||
|
|
||||||
// Generate an Access Token
|
// Generate an Access Token
|
||||||
export default function encode(data: any): string {
|
export default function encode(sessionId: string): string {
|
||||||
const { user, sessionId } = data
|
const token = jwt.sign({ sessionId }, CONFIG.JWT_SECRET, {
|
||||||
const { email, language, firstName, lastName } = user
|
|
||||||
const token = jwt.sign({ email, language, firstName, lastName, sessionId }, CONFIG.JWT_SECRET, {
|
|
||||||
expiresIn: CONFIG.JWT_EXPIRES_IN,
|
expiresIn: CONFIG.JWT_EXPIRES_IN,
|
||||||
// issuer: CONFIG.GRAPHQL_URI,
|
|
||||||
// audience: CONFIG.CLIENT_URI,
|
|
||||||
subject: sessionId.toString(),
|
subject: sessionId.toString(),
|
||||||
})
|
})
|
||||||
return token
|
return token
|
||||||
|
|||||||
@ -2,7 +2,17 @@ import gql from 'graphql-tag'
|
|||||||
|
|
||||||
export const login = gql`
|
export const login = gql`
|
||||||
query($email: String!, $password: String!) {
|
query($email: String!, $password: String!) {
|
||||||
login(email: $email, password: $password)
|
login(email: $email, password: $password) {
|
||||||
|
token
|
||||||
|
user {
|
||||||
|
email
|
||||||
|
username
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
language
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import createPersistedState from 'vuex-persistedstate'
|
import createPersistedState from 'vuex-persistedstate'
|
||||||
import VueJwtDecode from 'vue-jwt-decode'
|
// import VueJwtDecode from 'vue-jwt-decode'
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
@ -30,15 +30,16 @@ export const mutations = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
login: ({ dispatch, commit }, token) => {
|
login: ({ dispatch, commit }, data) => {
|
||||||
const decoded = VueJwtDecode.decode(token)
|
// const decoded = VueJwtDecode.decode(data.token)
|
||||||
commit('token', token)
|
const { user } = data
|
||||||
commit('email', decoded.email)
|
commit('token', data.token)
|
||||||
commit('language', decoded.language)
|
commit('email', user.email)
|
||||||
commit('username', decoded.username)
|
commit('language', user.language)
|
||||||
commit('firstName', decoded.firstName)
|
commit('username', user.username)
|
||||||
commit('lastName', decoded.lastName)
|
commit('firstName', user.firstName)
|
||||||
commit('description', decoded.description)
|
commit('lastName', user.lastName)
|
||||||
|
commit('description', user.description)
|
||||||
},
|
},
|
||||||
logout: ({ commit, state }) => {
|
logout: ({ commit, state }) => {
|
||||||
commit('token', null)
|
commit('token', null)
|
||||||
|
|||||||
@ -77,7 +77,17 @@ describe('Vuex store', () => {
|
|||||||
describe('login', () => {
|
describe('login', () => {
|
||||||
const commit = jest.fn()
|
const commit = jest.fn()
|
||||||
const state = {}
|
const state = {}
|
||||||
const commitedData = 'token'
|
const commitedData = {
|
||||||
|
token: 'token',
|
||||||
|
user: {
|
||||||
|
email: 'user@example.org',
|
||||||
|
language: 'de',
|
||||||
|
username: 'peter',
|
||||||
|
firstName: 'Peter',
|
||||||
|
lastName: 'Lustig',
|
||||||
|
description: 'Nickelbrille',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
it('calls seven commits', () => {
|
it('calls seven commits', () => {
|
||||||
login({ commit, state }, commitedData)
|
login({ commit, state }, commitedData)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user