Skip to content

Commit

Permalink
Merge pull request #6410 from espoon-voltti/apigw-traceid-propagation
Browse files Browse the repository at this point in the history
Propagoidaan `traceId` servicelle kaikissa `/system`-requesteissa
  • Loading branch information
akheron authored Feb 21, 2025
2 parents 7f75642 + e0ac572 commit cb44dc1
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 49 deletions.
2 changes: 1 addition & 1 deletion apigw/src/enduser/dev-sfi-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function createDevSfiRouter(sessions: Sessions<'citizen'>): Router {
},
verifyUser: async (req) => {
const socialSecurityNumber = assertStringProp(req.body, 'preset')
const person = await citizenLogin({
const person = await citizenLogin(req, {
socialSecurityNumber,
firstName: '',
lastName: ''
Expand Down
4 changes: 2 additions & 2 deletions apigw/src/enduser/keycloak-citizen-saml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ const Profile = z.object({

export const authenticate = authenticateProfile(
Profile,
async (samlSession, profile) => {
async (req, samlSession, profile) => {
const socialSecurityNumber = profile.socialSecurityNumber
if (!socialSecurityNumber)
throw Error('No socialSecurityNumber in evaka IDP SAML data')

const person = await citizenLogin({
const person = await citizenLogin(req, {
socialSecurityNumber,
firstName: profile.firstName ?? '',
lastName: profile.lastName ?? '',
Expand Down
2 changes: 1 addition & 1 deletion apigw/src/enduser/routes/auth-weak-login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const authWeakLogin = (
}
}

const { id } = await citizenWeakLogin(body)
const { id } = await citizenWeakLogin(req, body)
const user: EvakaSessionUser = {
id,
authType: 'citizen-weak',
Expand Down
8 changes: 4 additions & 4 deletions apigw/src/enduser/suomi-fi-saml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ const ssnRegex = /^[0-9]{6}[-+ABCDEFUVWXY][0-9]{3}[0-9ABCDEFHJKLMNPRSTUVWXY]$/

const authenticateCitizen = authenticateProfile(
Profile,
async (samlSession, profile) => {
async (req, samlSession, profile) => {
const socialSecurityNumber = profile[SUOMI_FI_SSN_KEY]?.trim()
if (!socialSecurityNumber) throw Error('No SSN in SAML data')
if (!ssnRegex.test(socialSecurityNumber)) {
logWarn('Invalid SSN received from Suomi.fi login')
}
const person = await citizenLogin({
const person = await citizenLogin(req, {
socialSecurityNumber,
firstName: profile[SUOMI_FI_GIVEN_NAME_KEY]?.trim() ?? '',
lastName: profile[SUOMI_FI_SURNAME_KEY]?.trim() ?? ''
Expand Down Expand Up @@ -72,13 +72,13 @@ export function createCitizenSuomiFiIntegration(

const authenticateEmployee = authenticateProfile(
Profile,
async (samlSession, profile) => {
async (req, samlSession, profile) => {
const socialSecurityNumber = profile[SUOMI_FI_SSN_KEY]?.trim()
if (!socialSecurityNumber) throw Error('No SSN in SAML data')
if (!ssnRegex.test(socialSecurityNumber)) {
logWarn('Invalid SSN received from Suomi.fi login')
}
const person = await employeeSuomiFiLogin({
const person = await employeeSuomiFiLogin(req, {
ssn: profile[SUOMI_FI_SSN_KEY],
firstName: profile[SUOMI_FI_GIVEN_NAME_KEY],
lastName: profile[SUOMI_FI_SURNAME_KEY]
Expand Down
4 changes: 2 additions & 2 deletions apigw/src/internal/ad-saml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ export function createSamlAdIntegration(
) {
const authenticate = authenticateProfile(
Profile,
async (samlSession, profile) => {
async (req, samlSession, profile) => {
const aad = profile[config.userIdKey]
if (!aad || typeof aad !== 'string')
throw Error('No user ID in SAML data')
const person = await employeeLogin({
const person = await employeeLogin(req, {
externalId: `${config.externalIdPrefix}:${aad}`,
firstName: profile[AD_GIVEN_NAME_KEY] ?? '',
lastName: profile[AD_FAMILY_NAME_KEY] ?? '',
Expand Down
1 change: 1 addition & 0 deletions apigw/src/internal/dev-ad-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export function createDevAdRouter(sessions: Sessions<'employee'>): Router {
verifyUser: async (req) => {
const preset = assertStringProp(req.body, 'preset')
const person = await employeeLogin(
req,
Employee.parse(preset === 'new' ? req.body : JSON.parse(preset))
)
return {
Expand Down
2 changes: 1 addition & 1 deletion apigw/src/internal/dev-sfi-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function createDevEmployeeSfiRouter(
const persons = await getVtjPersons()
const person = persons.find((c) => c.ssn === ssn)
if (!person) throw new Error(`No VTJ person found with SSN ${ssn}`)
const employee = await employeeSuomiFiLogin({
const employee = await employeeSuomiFiLogin(req, {
ssn,
firstName: person.firstName,
lastName: person.lastName
Expand Down
4 changes: 2 additions & 2 deletions apigw/src/internal/keycloak-employee-saml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ const Profile = z.object({

const authenticate = authenticateProfile(
Profile,
async (samlSession, profile) => {
async (req, samlSession, profile) => {
const id = profile.id
if (!id) throw Error('No user ID in evaka IDP SAML data')
const person = await employeeLogin({
const person = await employeeLogin(req, {
externalId: `evaka:${id}`,
firstName: profile.firstName ?? '',
lastName: profile.lastName ?? '',
Expand Down
2 changes: 1 addition & 1 deletion apigw/src/shared/routes/saml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export function createSamlIntegration<T extends SessionType>(
}
}
try {
const user = await authenticate(profile)
const user = await authenticate(req, profile)
await sessions.login(req, user)
logAuditEvent(eventCode('sign_in'), req, 'User logged in successfully')

Expand Down
6 changes: 4 additions & 2 deletions apigw/src/shared/saml/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,23 @@ export function createSamlConfig(
}

export type AuthenticateProfile = (
req: express.Request,
profile: Profile
) => Promise<EvakaSessionUser>

export function authenticateProfile<T>(
schema: z.ZodType<T>,
authenticate: (
req: express.Request,
samlSession: SamlSession,
profile: T
) => Promise<EvakaSessionUser>
): AuthenticateProfile {
return async (profile) => {
return async (req, profile) => {
const samlSession = SamlSessionSchema.parse(profile)
const parseResult = schema.safeParse(profile)
if (parseResult.success) {
return await authenticate(samlSession, parseResult.data)
return await authenticate(req, samlSession, parseResult.data)
} else {
throw new Error(
`SAML ${profile.issuer} profile parsing failed: ${parseResult.error.message}`
Expand Down
50 changes: 17 additions & 33 deletions apigw/src/shared/service-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export type ServiceRequestHeaders = Partial<
>

export function createServiceRequestHeaders(
req: express.Request | undefined,
req: express.Request,
userHeader: string | undefined
) {
const headers: ServiceRequestHeaders = {
Expand All @@ -48,10 +48,10 @@ export function createServiceRequestHeaders(
if (userHeader) {
headers['X-User'] = userHeader
}
if (req?.traceId) {
if (req.traceId) {
headers['X-Request-ID'] = req.traceId
}
const mockedTime = req?.get('EvakaMockedTime')
const mockedTime = req.get('EvakaMockedTime')
if (mockedTime) {
headers['EvakaMockedTime'] = mockedTime
}
Expand Down Expand Up @@ -102,27 +102,25 @@ export interface CitizenUserResponse {
}

export async function employeeLogin(
req: express.Request,
employee: EmployeeLoginRequest
): Promise<EmployeeUser> {
const { data } = await client.post<EmployeeUser>(
`/system/employee-login`,
employee,
{
headers: createServiceRequestHeaders(undefined, systemUserHeader)
}
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
}

export async function employeeSuomiFiLogin(
req: express.Request,
employee: EmployeeSuomiFiLoginRequest
): Promise<EmployeeUser> {
const { data } = await client.post<EmployeeUser>(
`/system/employee-sfi-login`,
employee,
{
headers: createServiceRequestHeaders(undefined, systemUserHeader)
}
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
}
Expand All @@ -134,9 +132,7 @@ export async function getEmployeeDetails(
try {
const { data } = await client.get<EmployeeUserResponse>(
`/system/employee/${employeeId}`,
{
headers: createServiceRequestHeaders(req, systemUserHeader)
}
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
} catch (e: unknown) {
Expand All @@ -149,14 +145,13 @@ export async function getEmployeeDetails(
}

export async function citizenLogin(
req: express.Request,
person: CitizenLoginRequest
): Promise<CitizenUser> {
const { data } = await client.post<CitizenUser>(
`/system/citizen-login`,
person,
{
headers: createServiceRequestHeaders(undefined, systemUserHeader)
}
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
}
Expand All @@ -167,14 +162,13 @@ interface CitizenWeakLoginRequest {
}

export async function citizenWeakLogin(
req: express.Request,
request: CitizenWeakLoginRequest
): Promise<CitizenUser> {
const { data } = await client.post<CitizenUser>(
`/system/citizen-weak-login`,
request,
{
headers: createServiceRequestHeaders(undefined, systemUserHeader)
}
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
}
Expand Down Expand Up @@ -210,9 +204,7 @@ export async function validatePairing(
const { data } = await client.post<MobileDeviceIdentity>(
`/system/pairings/${encodeURIComponent(id)}/validation`,
request,
{
headers: createServiceRequestHeaders(req, systemUserHeader)
}
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
}
Expand All @@ -233,9 +225,7 @@ export async function identifyMobileDevice(
try {
const { data } = await client.get<MobileDeviceIdentity | undefined>(
`/system/mobile-identity/${encodeURIComponent(token)}`,
{
headers: createServiceRequestHeaders(req, systemUserHeader)
}
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
} catch (e: unknown) {
Expand All @@ -254,12 +244,8 @@ export async function authenticateMobileDevice(
try {
const { data } = await client.post<MobileDevice | undefined>(
`/system/mobile-devices/${encodeURIComponent(id)}`,
{
userAgent: req.headers['user-agent'] ?? ''
},
{
headers: createServiceRequestHeaders(req, systemUserHeader)
}
{ userAgent: req.headers['user-agent'] ?? '' },
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
} catch (e: unknown) {
Expand All @@ -282,9 +268,7 @@ export async function employeePinLogin(
const { data } = await client.post<EmployeePinLoginResponse>(
`/system/mobile-pin-login`,
req.body,
{
headers: createServiceRequestHeaders(req, systemUserHeader)
}
{ headers: createServiceRequestHeaders(req, systemUserHeader) }
)
return data
}

0 comments on commit cb44dc1

Please sign in to comment.