Closed traycn closed 3 months ago
This ticket is ready to be picked up, thank you @traycn
I'm going to jot a ChatGPT response that I generated when I asked about measures we can take to secure our access tokens. I think this is relevant for all tokens we use, considering we don't have a backend:
cc @Skydodle
Certainly! Without a backend server, you have to rely on alternative methods to secure your access token. Here's how you can adapt the suggestions: - Environment Variables: Since you don't have a backend server to store environment variables, you can't directly use this approach. Instead, consider storing the access token securely in your frontend code. Use techniques like encryption or obfuscation to make it more difficult for users to extract the token from your code. - Token Scope: When generating the access token, ensure that you only grant it the permissions necessary for the specific actions it needs to perform. Avoid granting excessive permissions that could potentially be misused if the token is compromised. - Client-side Proxy: Implement a client-side proxy using serverless functions or cloud services. For example, you can use AWS Lambda or Azure Functions to create lightweight proxy functions that make requests to GitHub's API on behalf of your frontend application. These functions can securely handle the access token and enforce access control policies. - Request Validation: Even though you don't have a backend server, you can still implement some level of request validation on the client-side. Validate requests to ensure they meet certain criteria before making API calls. This can include checking for required parameters, sanitizing input, and verifying the integrity of the request. - Token Rotation: Although you can't rotate access tokens as easily without a backend server, you can manually regenerate and update the token in your frontend code when necessary. Make sure to follow best practices for securely storing and updating the token. - Token Expiry: Set an expiry time for the access token and handle token expiration gracefully in your frontend code. When the token expires, prompt the user to reauthenticate or automatically refresh the token if possible. Regarding token swapping strategies when a token is suspected to be misused: - Monitoring and Logging: Implement client-side logging and monitoring to track API usage and detect any suspicious activity associated with the access token. Monitor network requests, error logs, and other relevant metrics to identify potential security threats. - Token Revocation: If you suspect that a token has been compromised, manually revoke the token through GitHub's interface. Update your frontend code to use a new token and consider implementing additional security measures to prevent similar incidents in the future. - Token Blacklisting: Maintain a blacklist of revoked or compromised tokens locally in your frontend code. Update your application to reject requests using blacklisted tokens and notify users of the security incident. - User Notifications: Notify users of any suspicious activity detected in their account or associated with their access token. Provide clear instructions on how to secure their account and mitigate potential risks. By adapting these strategies to your frontend-only architecture, you can still enhance the security of your access tokens and protect your resources from unauthorized access.
Hello, I've been thinking about a different approach using AWS Lambda that might be worth considering.
POST
request to the serverless function URL (which is the Lambda function below).POST
request to a URL provided by the API Gateway, which then invokes the Lambda function. Setting up the API Gateway does not require any coding at all, it's simply choosing configurations via the AWS platform.POST
request, and how we want the data to appear in Github issue (which is dictated by Github API so we only have to follow instructions).In my opinion, AWS Lambda would be a quick and simple setup as most steps are take care of by AWS automations. However, my opinion is definitely biased since I had some exposure with AWS. I'm happy to hear other options or dicuss any possible issues with this route.
@ryanfchase
There is also one major issue regardless of how we end up implementing this. We need to generate an access token in order to post a Github issue from whatever implementation we chose. I checked around for organizational permissions, and I think only Bonnie and Chelsea can generate access tokens. This might be something we have to bring up to Bonnie to see what to do best.
ETA: Sunday 6/16 Availability: M-Sun after 6pm
@ryanfchase
For the Personal Access Token, I would suggest to set it as no expiration, with the following scopes:
Mandatory:
repo
scope: mandatory for octokit and for CRUD operations on issues in repoOptional Add-Ons For Future Functionality Expansion
workflow
: for triggering Github Actions workflows in response to form submissionadmin:repo_hook
: to manage webhooks, which can send real-time data to exteranl services when events (push, PRs, etc.) occured in the repo. No solid ideas yet, but could be useful later if we want to use EmailJS to send more than a confirmation email to usersnotification
: access to notification for events, also thought it could be useful later maybe.@Skydodle I need to have the admin team create a bot account for us in order to automate the opening of issues.
Here's my references to how the website team is utilizing a bot in a smiliar capacity:
In the meantime, please develop with your own access token.
Assigning myself while I create the emailjs deliverables ETA 6-8-24 Availability: weekends before 7p
The EmailJS service has been set up within the 311-DataDev vault in 1Password.
311 Data Contact Page Reply Service
311 Data Contact Page Reply Template
I'm also opening a ticket on the PM team (and possibly UIUX team) to take a pass at the contents of the page: https://github.com/hackforla/311-data/issues/1754
@Skydodle I know you're sick so take your time. When you can, please provide an update on this ticket and an ETA of when you believe it will be complete.
ETA: Friday 6/21 EOD Avaialbility: Friday to Monday after 5pm
I'm realizing that to fully complete this ticket, I think this will become dependent on one other ticket:
I was thinking that maybe it would also be dependent on the email template we are designing... but I think if we provide the css to the emailJS template on our account, @Skydodle's code is agnostic to how the email's formatting and inner contents.
In any case, @Skydodle let me know when you hit a point where you are fully blocked by #1769 -- and I will move this ticket to Icebox and list its dependency.
Leaving note regarding the personal access token required for the octokit service. Currently for local development purpose, I created my own Github PAT. The PM team will need to create a HFLA bot account with its own PAT to use for the app in production.
For your reference, the scopes I chose when creating the PAT were repo
, workflow
, and notification
.
Did some testing for security, and found that our idea of directly using Octokit from client to create Github issue without a server is highly insecure. Even if we stored the Github Personal Access Token (PAT) in Github Secrets for production, at build time any process.env
reference will be replace with the actual API keys. These keys can be exposed to anyone who inspect the JS code running in the browser.
I inspected our live site with Chrome Dev Tools and search for our Mapbox API token, and indeed it was easily found. See screenshot below, last line contains Mapbox access token:
The Mapbox API key is for public usage on Mapbox, which doesnt have any effect on our Github if stolen. The Github PAT however, if exposed can pose a serious security threat to our organization.
1. Create a Google Form
2. Open Google Apps Script
3. Write the Google Apps Script
Here’s an example script that triggers when the form is submitted:
function onFormSubmit(e) {
var title = e.values[1];
var body = e.values[2];
var payload = {
"title": title,
"body": body
};
var options = {
"method" : "post",
"headers": {
"Authorization": "token YOUR_GITHUB_PAT"
},
"payload": JSON.stringify(payload),
"contentType": "application/json"
};
var response = UrlFetchApp.fetch("https://api.github.com/repos/YOUR_GITHUB_USERNAME/YOUR_REPO/issues", options);
Logger.log(response.getContentText());
}
function createTrigger() { var form = FormApp.openById("YOUR_FORM_ID"); ScriptApp.newTrigger("onFormSubmit") .forForm(form) .onFormSubmit() .create(); }
</p>
</details>
- Note: Need a Google account for our team if not already have one, and need to ensure access to the Google Apps Script project is restricted to trusted users.
---
### Considerations
@ryanfchase I understand you want to go with option 2 to keep the application "frontend only". In my opinion, both options does the same thing. They both require the client to send a request to an outside server:
- In Option 1, the current contact form hits the Netlify service we created
- In Option 2, the Google Form hits the Google Apps Scripts API.
Both options has the benefit of storing the PAT token securely outside of our client code base.
The major difference we need to consider is the frontend design we intend to present to the users, which we should open up for discussion with design team and maybe research team:
- Option 1 will use the existing contact form we have on the Contact page
- Option 2 will either:
- Embed the Google Form on the Contact page OR
- Some other design that integrate the Google Form, something maybe the design team can come up with
- Team to discuss which form would be user-centric on design, usability, and styling consistence with the rest of the app, etc.
Hi @Skydodle,
Please leave a comment with the following items:
Updated ETA: Friday 6/28 Avaialbility: Friday to Monday after 5pm
Closing this ticket as we are taking a different implementation from this issue's approach. The original proposal exposes the access token without a server to store it. This ticket is replaced with #1780.
Modifying as Not Planned due to technical limitations
Overview
We need to update the contact form to use front-end only services for 311-Data users to submit their concerns as a github issue. Users would then receive a confirmation email.
Action Items
Octokit - POST body data model
.Contact Form field values
andEmail template values
.Resources/Instructions
Octokit
Octokit/Core.js documentation Octokit/Core.js package Create a new Github Access Token Create a new issue - Octokit documentation
EmailJS
Sign-Up for EmailJS Send an email after Contact Form is submitted
Other Details
For reference to the data we are using, the values collected on the forms submit are below.
Create a Github Issue using Octokit/Core.js
Example POST body data model (open to change)
Dependency