Skip to content

Commit

Permalink
Merge pull request #30 from seanbirchall/development
Browse files Browse the repository at this point in the history
UPDATE: auth service
  • Loading branch information
seanbirchall authored Nov 27, 2024
2 parents 7d006ba + c762572 commit c100ca2
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 112 deletions.
198 changes: 87 additions & 111 deletions service/auth/index.js
Original file line number Diff line number Diff line change
@@ -1,137 +1,113 @@
// app.js
require('dotenv').config();
const express = require('express');
const axios = require('axios');
const cookieParser = require('cookie-parser');

const cookieParser = require('cookie-parser'); // Optional, for parsing cookies
const axios = require('axios'); // For making requests to Cognito
const app = express();
app.use(cookieParser());

// AWS Cognito Config
const config = {
COGNITO_DOMAIN: process.env.COGNITO_DOMAIN,
CLIENT_ID: process.env.CLIENT_ID,
CLIENT_SECRET: process.env.CLIENT_SECRET,
REDIRECT_URI: process.env.REDIRECT_URI,
COOKIE_DOMAIN: process.env.COOKIE_DOMAIN || 'localhost',
FRONTEND_URL: process.env.FRONTEND_URL || 'http://localhost:3000'
};

// Cookie configuration
const cookieConfig = {
httpOnly: true,
secure: process.env.NODE_ENV === 'production', // true in production
sameSite: 'lax',
domain: config.COOKIE_DOMAIN,
path: '/',
maxAge: 7 * 24 * 60 * 60 * 1000 // 7 days
};
app.use(cookieParser());

// Exchange authorization code for tokens
async function getTokensFromCode(code) {
const params = new URLSearchParams({
grant_type: 'authorization_code',
client_id: config.CLIENT_ID,
client_secret: config.CLIENT_SECRET,
code: code,
redirect_uri: config.REDIRECT_URI
});
// Redirect endpoint
app.get('/callback', async (req, res) => {
const { code } = req.query; // Get the authorization code from the redirect
if (!code) {
console.log('no auth code');
return res.status(400).send('Authorization code is missing');
}

try {
// Exchange the authorization code for tokens
const response = await axios.post(
`${config.COGNITO_DOMAIN}/oauth2/token`,
params.toString(),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
process.env.COGNITO_TOKEN_URL,
new URLSearchParams({
grant_type: 'authorization_code',
client_id: process.env.COGNITO_CLIENT_ID,
client_secret: process.env.COGNITO_CLIENT_SECRET,
code,
redirect_uri: 'https://reprex.org/auth/redirect',
}),
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
);

return response.data;
const { access_token, refresh_token } = response.data;

if (!access_token) {
console.warn('access token is missing');
}
if (!refresh_token) {
console.warn('refresh token is missing');
}

if(access_token) {
res.cookie('access_token', access_token, {
httpOnly: true,
secure: true,
sameSite: 'Strict',
maxAge: 3600 * 1000, // 1 hour
});
}
if(refresh_token) {
res.cookie('refresh_token', refresh_token, {
httpOnly: true,
secure: true, // Use true in production
sameSite: 'Strict',
maxAge: 5 * 24 * 3600 * 1000, // 7 days
});
}

// redirect to reprex ide
res.redirect('/index.html');
} catch (error) {
console.error('Error exchanging code for tokens:', error.response?.data || error.message);
throw error;
console.error('error exchanging code for tokens:', error.response?.data || error.message);
res.status(500).send('Authentication failed');
}
}
});

// Refresh token endpoint
app.post('/auth/refresh', async (req, res) => {
const refreshToken = req.cookies.refreshToken;
app.get('/logout', async (req, res) => {
// Clear cookies
res.clearCookie('access_token');
res.clearCookie('refresh_token');

// Redirect to Cognito logout
const logoutUrl = `${process.env.COGNITO_DOMAIN}/logout?` +
`client_id=${process.env.COGNITO_CLIENT_ID}&` +
`logout_uri=${encodeURIComponent('https://reprex.org')}`;

res.redirect(logoutUrl);
});

if (!refreshToken) {
return res.status(401).json({ error: 'No refresh token found' });
}
app.get('/refresh', async (req, res) => {
const refreshToken = req.cookies.refresh_token;

try {
const params = new URLSearchParams({
grant_type: 'refresh_token',
client_id: config.CLIENT_ID,
client_secret: config.CLIENT_SECRET,
refresh_token: refreshToken
});

// Attempt to get a new access token using the refresh token
const response = await axios.post(
`${config.COGNITO_DOMAIN}/oauth2/token`,
params.toString(),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
process.env.COGNITO_TOKEN_URL,
new URLSearchParams({
grant_type: 'refresh_token',
client_id: process.env.COGNITO_CLIENT_ID,
client_secret: process.env.COGNITO_CLIENT_SECRET,
refresh_token: refreshToken
}),
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
);

// Set new access token cookie
res.cookie('accessToken', response.data.access_token, cookieConfig);

res.json({ success: true });
} catch (error) {
console.error('Error refreshing token:', error.response?.data || error.message);
res.clearCookie('accessToken', cookieConfig);
res.clearCookie('refreshToken', cookieConfig);
res.status(401).json({ error: 'Failed to refresh token' });
}
});

// Callback endpoint
app.get('/auth/callback', async (req, res) => {
const { code, error } = req.query;

if (error) {
console.error('OAuth error:', error);
return res.redirect(`${config.FRONTEND_URL}/login?error=${error}`);
}

try {
const tokens = await getTokensFromCode(code);
const { access_token } = response.data;

// Set cookies
res.cookie('accessToken', tokens.access_token, cookieConfig);
res.cookie('refreshToken', tokens.refresh_token, {
...cookieConfig,
maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days for refresh token
// Set new access token cookie
res.cookie('access_token', access_token, {
httpOnly: true,
secure: true,
sameSite: 'Strict',
maxAge: 3600 * 1000, // 1 hour
});

// Redirect to frontend
res.redirect(config.FRONTEND_URL);
} catch (error) {
console.error('Callback error:', error);
res.redirect(`${config.FRONTEND_URL}/login?error=callback_failed`);
// Refresh token is invalid or expired
res.clearCookie('access_token');
res.clearCookie('refresh_token');
}
});

// Logout endpoint
app.post('/auth/logout', (req, res) => {
res.clearCookie('accessToken', cookieConfig);
res.clearCookie('refreshToken', cookieConfig);
res.json({ success: true });
});

// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'healthy' });
});

app.listen(4000, () => {
console.log(`Auth server running on port 4000`);
// Start the server
app.listen(3001, () => {
console.log('auth service is running on 3001');
});
2 changes: 1 addition & 1 deletion service/git/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,5 @@ app.post('/webhook', async (req, res) => {

// Start server
app.listen(3000, () => {
console.log('GitHub webhook service running on port 3000');
console.log('git service is running on port 3000');
});

0 comments on commit c100ca2

Please sign in to comment.