Broken Academy Single Sign On
The application is up and running but when you try to sign in, you’re getting an error. These errors show up in Sentry, which is great, but how can we use Tracing and Logs to help troubleshoot the issue?

Learning Objectives
By the end of this module, you will:
- Create Custom Spans that will track specific attributes within your application
- Use Trace Explorer to search for specific spans that match issues in your environment
- Explore trace waterfalls to understand where in the trace issue happens
- Implement logs in your application to give you more context around the issues happening within your application
- Search and review logs to help troubleshoot issues in your application
Frontend Implementation
Let’s start by instrumenting the frontend authentication flow to track login attempts and user credential processing.
-
Add Sentry Import to Frontend Login Component
Navigate to the
/apps/frontend/src/components/auth/LoginForm.tsx
file and add the Sentry import at the top:import * as Sentry from '@sentry/react'; -
Set Up Frontend Logging
Add the logger destructuring after your imports to access Sentry’s logging functionality:
const { logger } = Sentry -
Replace the Complete handleSSO Function
Replace the entire ‘handleSSO’ function with this instrumented version:
const handleSSO = async (provider: string) => {setError('');setIsLoading(true);try {await Sentry.startSpan({name: 'sso.authentication.frontend',op: 'auth.sso',attributes: {'auth.provider': provider,},},async (span) => {const userCredentials = fetchSSOUserCredentials(provider);logger.info(logger.fmt`Logging user ${userCredentials.email} in using ${provider}`);span.setAttributes({'auth.user.id': userCredentials.id,'auth.user.email': userCredentials.email,'auth.user.name': userCredentials.name,'auth.user.avatar': userCredentials.avatar,});const loginSignature = createAuthenticationToken(userCredentials, provider);span.setAttributes({'auth.login_signature.defined': loginSignature !== undefined && loginSignature !== null,});await ssoLogin(provider);});navigate('/');} catch (err: any) {logger.error(logger.fmt`Failed to login with ${provider} - issue with loginSignature`);setError(`Failed to login with ${provider} - issue with loginSignature`);throw err;} finally {setIsLoading(false);}}; -
Test Frontend Tracing
Try logging in again. Navigate to Explore > Traces in Sentry’s left navigation menu, and search using the
span.description
filter withsso.authentication.frontend
as the value. -
Examine the Trace
Clicking into one of the spans will show you the trace waterfall where you can examine the properties of any of he spans submitted.
-
Examine the Logs
Check the Explore > Logs tab for the log entries created by
logger.info
andlogger.error
calls.
Backend Implementation
Now let’s instrument the backend authentication flow to trace the server-side processing and identify where the issue occurs.
-
Add Sentry Import to Backend Auth Routes
Navigate to the
/apps/server/modules/auth/routes.ts
file and add the Sentry import at the top:import * as Sentry from '@sentry/node'; -
Set Up Backend Logging
Add the logger destructuring after your imports:
const { logger } = Sentry -
Replace the Complete SSO Route
Replace the entire
authRoutes.post('/sso/:provider'
route with this instrumented version:authRoutes.post('/sso/:provider', async (req, res) => {try {const { provider } = req.params;const { loginSignature } = req.body;await Sentry.startSpan({name: 'sso.authentication.server',op: 'auth.sso.verify',attributes: {'auth.provider': provider,'auth.login_signature.provided': !!loginSignature,'http.method': req.method,'http.route': '/sso/:provider',},},async (span) => {logger.info(logger.fmt`SSO login attempt with ${provider}`);logger.info(logger.fmt`Login signature provided: ${!!loginSignature}`);// Add more attributes based on request dataspan.setAttributes({'auth.request.body_size': JSON.stringify(req.body).length,'auth.request.has_signature': loginSignature !== undefined,});// TOFIX Module 1: SSO Login with missing login signatureconst signaturePayload = JSON.parse(atob(loginSignature)); // This will throw when loginSignature is undefined// Add signature payload details to spanspan.setAttributes({'auth.signature.user_id': signaturePayload.sub || null,'auth.signature.email': signaturePayload.email || null,'auth.signature.name': signaturePayload.name || null,'auth.signature.provider': signaturePayload.provider || null,'auth.signature.issued_at': signaturePayload.iat || null,'auth.signature.expires_at': signaturePayload.exp || null,'auth.signature.has_user_data': !!(signaturePayload.userData),});// Use the rich fake user data from the signature payload, with sensible defaultsconst fakeUserData = signaturePayload.userData || {};// Add user data details to spanspan.setAttributes({'auth.user.id': fakeUserData.id || null,'auth.user.email': fakeUserData.email || null,'auth.user.name': fakeUserData.name || null,'auth.user.company': fakeUserData.company || null,'auth.user.job_title': fakeUserData.jobTitle || null,});const ssoUser = {id: fakeUserData.id || createId(),email: fakeUserData.email || `${provider}.user@example.com`,name: fakeUserData.name || `${provider.charAt(0).toUpperCase() + provider.slice(1)} User`,firstName: fakeUserData.firstName || 'Demo',lastName: fakeUserData.lastName || 'User',username: fakeUserData.username || 'demo.user',avatar: fakeUserData.avatar || 'https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg',company: fakeUserData.company || 'Demo Company',jobTitle: fakeUserData.jobTitle || 'Software Developer',phone: fakeUserData.phone || '+1-555-0123',workEmail: fakeUserData.workEmail || fakeUserData.email,role: 'student',provider: provider,signatureClaims: {sub: signaturePayload.sub,exp: signaturePayload.exp,metadata: {permissions: [],roles: []}},socialProfile: {profileImage: fakeUserData.avatar || 'https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg',verified: true,provider: provider},linkedAccounts: [{provider: provider,externalId: signaturePayload.sub,profile: {username: fakeUserData.username || (fakeUserData.email || signaturePayload.email || 'user').split('@')[0],avatar: fakeUserData.avatar || 'https://images.pexels.com/photos/220453/pexels-photo-220453.jpeg'}}]};// Add final authentication result to spanspan.setAttributes({'auth.result.user_id': ssoUser.id,'auth.result.success': true,'auth.result.provider_verified': true,});const responseData = {user: ssoUser,token: `sso-token-${createId()}`,expiresIn: '24h'};logger.info(logger.fmt`Successful SSO login with ${provider}`);res.json(responseData);});} catch (error: any) {Sentry.captureException(error, {tags: {operation: 'sso.authentication.backend',provider: req.params.provider,},extra: {provider: req.params.provider,hasLoginSignature: !!req.body.loginSignature,requestBody: req.body,},});logger.error(logger.fmt`SSO login error for ${req.params.provider}:`, error);throw error;}}); -
Test Backend Tracing
Try logging in again and observe the trace and logs by viewing the Explore > Traces and using the Trace Explorer to search for
sso.authentication.server
. -
Examine the Trace
Clicking into one of the spans will show you the trace waterfall where you can examine the properties of any of he spans submitted.
-
Examine the Logs
You should now see the complete authentication flow traced from frontend to backend, and notice that the loginSignature is being created on the frontend but not being passed properly to the server.
Analyzing the Issue
When we explore these traces and logs, we can see an inconsistency - the loginSignature is being created on the frontend, but not being passed properly to the server.
Fixing the Issue
Fortunately the issue is a trivial one to fix! We determined that our loginSignature wasn’t being passed properly from the frontend to the server, and we can add it to the login request.
-
Update Frontend to Pass Login Signature
In the frontend authentication flow, replace:
await ssoLogin(provider);With:
await ssoLogin(provider, loginSignature);This will pass the loginSignature to the server, and we’ll be able to see it in the trace and logs.
Once this is complete, give login a try again and you’ll see the loginSignature being passed to the server and your login will be successful! You’ll be at the landing screen of Sentry Academy.
