Authentication
and Authorization
Systems development and frameworks
Lecturer: Robert Schäfer
Frontend
Backend
Database
API
Devops
Mobile
Web
Authentication and Authorization are one of the most important responsibilities of the backend
jwt.io: inspect any JWT
Client
Server
Login
Sign token using a symmetric (or asymmetric) algorithm
Request with
Bearer token
Verify JWT with secret
(or public key)
Auth0 scenario
Client
Server
Login
Sign token using an asymmetric algorithm
Request with
Bearer token
Verify JWT with public key
3rd party
DO
Verify and decode JWT
in context function
import { JWT_SECRET } from './config.js'
import jwt from 'jsonwebtoken'
export default function context ({ req }) {
let token = req.headers.authorization || ''
token = token.replace('Bearer ', '')
try {
const decodedJwt = jwt.verify(
token,
JWT_SECRET
)
return { decodedJwt }
} catch (e) {
return {}
}
}
Grapqhl-middleware: adds execution layer before and after your resolvers
“unmaintained” warning as of November 23rd 2020
Functional programming with graphql-shield
const isAuthenticated = rule({ cache: 'contextual' })(
async (parent, args, { dataSources }, info) => {
return !!dataSources.db.currentUser()
},
)
export default shield({
Mutation: {
addFruitToBasket: isAuthenticated,
}
})
First method call
const isAuthenticated = rule({ cache: 'contextual' })(
async (parent, args, { dataSources }, info) => {
return !!dataSources.db.currentUser()
},
)
export default shield({
Mutation: {
addFruitToBasket: isAuthenticated,
}
})
Second method call
const isAuthenticated = rule({ cache: 'contextual' })(
async (parent, args, { dataSources }, info) => {
return !!dataSources.db.currentUser()
},
)
export default shield({
Mutation: {
addFruitToBasket: isAuthenticated,
}
})
This method argument is a callback
const isAuthenticated = rule({ cache: 'contextual' })(
async (parent, args, { dataSources }, info) => {
return !!dataSources.db.currentUser()
},
)
export default shield({
Mutation: {
addFruitToBasket: isAuthenticated,
}
})
Return value must be yet another method
const isAuthenticated = rule({ cache: 'contextual' })(
async (parent, args, { dataSources }, info) => {
return !!dataSources.db.currentUser()
},
)
export default shield({
Mutation: {
addFruitToBasket: isAuthenticated,
}
})
DO
Authorize write access
as soon as possible
export default shield({
Query: {
'*': deny,
Category: allow,
notifications: isAuthenticated,
// ...
},
Mutation: {
'*': deny,
login: allow,
UpdateUser: onlyYourself,
CreatePost: isAuthenticated,
UpdatePost: isAuthor,
DeletePost: isAuthor,
// ...
}
})
DO
Authorize read access
in type resolvers
export default shield({
Query: {
// ...
},
Mutation: {
// ...
},
User: {
email: or(isMyOwn, isAdmin),
},
})
Exam questions