Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARC-1355 add jwt cookie #1234

Merged
merged 15 commits into from
Jun 6, 2022
Merged

ARC-1355 add jwt cookie #1234

merged 15 commits into from
Jun 6, 2022

Conversation

gxueatlassian
Copy link
Contributor

@gxueatlassian gxueatlassian commented Jun 2, 2022

Adding a new mechanism to protect user from connecting to other jira host.

https://developer.atlassian.com/cloud/confluence/cacheable-app-iframes-for-connect-apps/#retrieving-context-using-ap-context-gettoken-- - essentially we are doing what's recommended in the docs but passing the value in cookies, not in a payload/query parameter

@gxueatlassian gxueatlassian requested a review from a team as a code owner June 2, 2022 05:47
@@ -28,18 +29,22 @@ export enum TokenType {
context = "context"
}

export function extractJwtFromRequest(req: Request): string | undefined {
const tokenInQuery = req.query?.[JWT_PARAM];
let secureJiraHostInCookies;
Copy link
Contributor

Choose a reason for hiding this comment

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

This var will bleed between different requests

Copy link
Contributor

Choose a reason for hiding this comment

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

That's what we want :) Once the FF is on, the value will eventually be updated (2nd call after the flip). Given the distributed nature of feature-flags, this is OK imho

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, understand that, and the full story is:

  1. We want to have some feature flags to guard this code. But the middleware is NOT async at the moment, therefore can't use the feature flag (unless we make it async)
  2. I understand that making the middleware async should not have problem. But I also think turning middleware async vs have a global var here, the latter one is less risky.
  3. I understand the race condition of multi request, but I think they will all lead to expected result (which is "the flag will be used eventually" if turned on.

Unless you think there's still impact on this global var?


// JWT appears in both parameter and body will result query hash being invalid.
booleanFlag(BooleanFlags.SECURE_JIRAHOST_IN_COOKIES, false)
Copy link
Contributor

Choose a reason for hiding this comment

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

please use await instead

Copy link
Contributor

Choose a reason for hiding this comment

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

We don't want to change the whole chain to be async @mboudreau cause it is pretty long.

Comment on lines 54 to +55
document.cookie = "jiraHost=" + window.jiraHost + "; path=/; max-age=" + 60 * 5 + "; samesite=none; secure";
document.cookie = "jwt=" + window.jwt + "; path=/; max-age=" + 60 * 5 + "; samesite=none; secure";
Copy link
Contributor

Choose a reason for hiding this comment

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

We could probably do encodeURIComponent of the cookie values in case there's a semi-colon or something else in there.

@@ -2,7 +2,7 @@ import { Installation } from "models/installation";
import { NextFunction, Request, Response } from "express";
import { sendError, TokenType, verifySymmetricJwtTokenMiddleware } from "../jira/util/jwt";

const verifyJiraJwtMiddleware = (tokenType: TokenType) => async (
export const verifyJiraJwtMiddleware = (tokenType: TokenType) => async (
Copy link
Contributor

Choose a reason for hiding this comment

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

This shouldn't be exported

Copy link
Contributor

Choose a reason for hiding this comment

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

Well, we kinda need that...

@bgvozdev
Copy link
Contributor

bgvozdev commented Jun 3, 2022

@mboudreau Thanks a lot for looking in the PR. We discussed your concerns regarding using one middleware in another one with @gxueatlassian and agreed on the follwing:

  1. We cannot use directly verifySymmetricJwtTokenMiddleware because it requires secrets, and to have a secret, we need to fetch installation etc, which means essentially to duplicate the code from verifyJiraJwtMiddleware (the nested middleware we are calling).

  2. Probably the perfect way to do that would be to refactor verifyJiraJwtMiddleware so it won't be a middleware, but that would require quite some work and not quite to the point of the ticket: we are fixing a major security problem. If we really want to do that refactoring, we can do this in another PR, because it will touch other parts of the code, too (which are not related to our current ticket).

@mboudreau
Copy link
Contributor

I disagree. We're in this predicament for exactly the same reason: we had a security issue, so someone coded the verifyJwtMiddleware super quickly in a bad manner, but then never readdressed it and now we're still using that bad code to implement more bad code. In the time we are debating around this issue, creating a new verifyJwtToken function would have already been done with a lot less risk involved as it wouldn't affect any other system and the new code wouldn't rely on the old verify middleware. I personally think my version is less risky because there's less code in total, less files changed and less dependency on bad code.

But I won't stop you I guess.

@bgvozdev
Copy link
Contributor

bgvozdev commented Jun 3, 2022

Hey @mboudreau , we actually made it better because now we force JWT verification for all jiraHost paths. If you check, before there was not any validation at all, now you cannot just add another jiraHost into a request and get it through not validated....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants