Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Proposed Changes

Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change.
|Before|After|
|---|---|
|<insert-img>|<insert-img>|

# Jira Stories

- [LAB-xxx](https://oregonstate-innovationlab.atlassian.net/browse/LAB-xxx)

# Checklist

- [ ] This has been tested
- [ ] Self-documenting code
- [ ] Code is linted

# Instructions to review

Tell me what to do
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env
node_modules/
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
# GoogleSignInVerification
# Google Sign-In Verification

A Lambda function that verifies Google Sign-In tokens and retrieves user information. It can be integrated with a SwiftUI front-end application.

## Usage

The code provided in this repository implements an AWS Lambda function that serves as an API endpoint for verifying Google Sign-In tokens and retrieving user information. The API supports the following operations:

- `POST /verifyToken`: Verifies a Google Sign-In token provided in the request body and returns the user information if the token is valid.
- `GET /getUserInfo`: Retrieves user information based on the authenticated user's ID. This operation requires authentication.

To use this code, follow these steps:

1. Clone the repository:
`https://github.com/pavan3008/GoogleSignInVerification`

2. Install the required dependencies:
`npm install`

3. Configure the necessary environment variables, such as the CLIENT_ID, by updating the `.env` file.

4. Deploy the Lambda function to your AWS account using your preferred deployment method.

## Contributing

Contributions to this repository are welcome. If you encounter any issues or have suggestions for improvements, please open an issue or submit a pull request.

## License

This project is licensed under the MIT License.
96 changes: 96 additions & 0 deletions Users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();
const tableName = process.env.DYNAMODB_TABLE_NAME;

require('dotenv').config();
const clientId= process.env.CLIENT_ID;

const { OAuth2Client } = require('google-auth-library');

const client = new OAuth2Client(clientId);

async function verifyToken(idToken) {
try {
const ticket = await client.verifyIdToken({
idToken: idToken,
audience: clientId,
});
const payload = ticket.getPayload();
const userInfo = {
name: payload.name,
email: payload.email,
picture: payload.picture,
sub: payload.sub
};

const userId = userInfo.sub;
const params = {
TableName: tableName,
Key: {
'PK': `User${userId}`,
'SK': `User${userId}`
}
};
const result = await dynamodb.get(params).promise();

// Check if user already exists in the system
if (!result.Item) {
// Add user to the system
const user = {
username: userInfo.name,
email: userInfo.email
};
const putParams = {
TableName: tableName,
Item: {
'PK': `User${userId}`,
'SK': `User${userId}`,
'user_data': {
'username': user.username,
'email': user.email
}
}
};
await dynamodb.put(putParams).promise();
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove space for consistency

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code is linted.

return userInfo;
} catch (error) {
console.error('Error verifying Google ID token:', error);
throw new Error('Invalid Google ID token');
}
}

async function getUserInfoById(userId) {
try {
const params = {
TableName: tableName,
Key: {
'PK': `User${userId}`,
'SK': `User${userId}`
}
};

const result = await dynamodb.get(params).promise();

if (result.Item) {
const userData = result.Item.user_data;
const userInfo = {
userId: userId,
username: userData.username,
email: userData.email
};
return userInfo;
} else {
throw new Error('User not found');
}
} catch (error) {
console.error('Error retrieving user information:', error);
throw new Error('Failed to retrieve user information');
}
}

module.exports = {
verifyToken,
getUserInfoById
};
59 changes: 59 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const { verifyToken, getUserInfoById } = require('./Users');

exports.handler = async (event, context) => {
let responseHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
'Access-Control-Allow-Methods': 'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT',
};

try {
const httpMethod = event.httpMethod.toUpperCase();
const path = event.path;
const body = JSON.parse(event.body);

switch (httpMethod) {
case 'POST':
if (path === '/verifyToken') {
const { idToken } = body;
const userInfo = await verifyToken(idToken);
return {
statusCode: 200,
body: JSON.stringify({ message: 'Token verified successfully', userInfo }),
headers: responseHeaders,
};
}
break;
case 'GET':
if (path === '/getUserInfo') {
const userId = event.requestContext.authorizer.principalId;
const userInfo = await getUserInfoById(userId);
return {
statusCode: 200,
body: JSON.stringify({ message: 'User info retrieved successfully', userInfo }),
headers: responseHeaders,
};
}
break;

default:
return {
statusCode: 404,
body: JSON.stringify({ message: 'Not Found' }),
headers: responseHeaders,
};
}

return {
statusCode: 404,
body: JSON.stringify({ message: 'Not Found' }),
headers: responseHeaders,
};
} catch (err) {
return {
statusCode: 500,
body: JSON.stringify({ message: 'Internal Server Error' }),
headers: responseHeaders,
};
}
};
Loading