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

MBL-1214: Send OAuth token only in headers, not in request parameters #1954

Merged
merged 6 commits into from Feb 23, 2024

Conversation

amy-at-kickstarter
Copy link
Contributor

@amy-at-kickstarter amy-at-kickstarter commented Feb 22, 2024

📲 What

Send OAuth tokens only in the request headers, not in the request parameters.

🤔 Why

This is a security concern which we wanted to address with the MVP of OAuth. Moving the authorization parameters into headers is a best practice.

See: https://github.com/kickstarter/kickstarter/pull/26425 and https://github.com/kickstarter/kickstarter/pull/26432

🛠 How

Note that this isn't behind any flags. The server change to accept the OAuth token in the headers was made globally, for all V1 requests, and already applied for GraphQL. We decided a ramp-up would be difficult, due to how deep the headers are buried in our networking stack, and of limited use, compared to testing this change manually.

Also note that we are sometimes sending redundant headers, like both Authorization and X-Auth with the OAuth token. To the best of my knowledge, both V1 and GraphQL discard extra headers, so there's no harm in this - and it makes our code significantly simpler.

@@ -41,6 +41,26 @@ extension Service {
).handle_combine_dataResponse(service: self)
}

func requestWithAuthentication<Model: Decodable>(_ route: Route,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The amount of copy-paste here makes me unhappy. However, I poked around with a few ideas for refactoring, and realized it was going to take significantly more refactoring to make a dent in this. I decided that (for the moment) this was an OK evil.

Because this is only used by precisely one route, I would much rather have one ugly copy-pasted method than plumb an extra parameter throughout our whole networking stack. And I would rather ship this now than embark in a larger refactoring project for Route.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just to confirm: this is necessary because we're calling this as soon as we have the token; before the token has been set (since we set the token when we have the user as well)? If I'm understanding this correctly, I support this as an OK evil, especially if we still think we may get the user object returned with the token in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct. It's a catch-22 - our login method requires both a user and a token; but our new token exchange endpoint (for throttling/speed reasons) only returns the token, not the user. So we needed a way to fetch the user before we've actually completed login and saved the token to the apiService.

@@ -490,37 +490,6 @@ extension ServiceType {
return self.preparedRequest(forRequest: request, query: query)
}

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These methods are unused; deleting for clarity.

@@ -605,7 +599,6 @@ extension ServiceType {
var query: [String: String] = [:]
query["client_id"] = self.serverConfig.apiClientAuth.clientId
query["currency"] = self.currency
query["oauth_token"] = self.oauthToken?.token
Copy link
Contributor Author

Choose a reason for hiding this comment

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

👋 Goodbye, token in request params.

@@ -248,9 +247,6 @@ internal enum Route {
case .userSelf:
return (.GET, "/v1/users/self", [:], nil)

case let .userSelfWithToken(token):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unnecessary; handling this at the Service level.

}
.receive(on: RunLoop.main)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops, this wasn't applying to the fetchUserSelf_combine call because it happened before. 🤦‍♀️

@amy-at-kickstarter amy-at-kickstarter changed the title Feat/adyer/mbl 1214/auth token as header MBL-1214: Send OAuth token only in headers, not in request parameters Feb 22, 2024
@amy-at-kickstarter amy-at-kickstarter requested review from a team and ifosli and removed request for a team February 22, 2024 20:24
@amy-at-kickstarter amy-at-kickstarter self-assigned this Feb 22, 2024
@amy-at-kickstarter amy-at-kickstarter marked this pull request as ready for review February 22, 2024 20:44
@nativeksr
Copy link
Collaborator

SwiftFormat found issues:

File Rules
KsApi/ServiceTypeTests.swift:329:1 warning: (wrap) Wrap lines that exceed the specified maximum width.

Generated by 🚫 Danger

@amy-at-kickstarter amy-at-kickstarter force-pushed the feat/adyer/MBL-1214/auth-token-as-header branch from 4cf77e8 to 763799d Compare February 22, 2024 22:49
Copy link
Contributor

@ifosli ifosli left a comment

Choose a reason for hiding this comment

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

Very nice!

@@ -41,6 +41,26 @@ extension Service {
).handle_combine_dataResponse(service: self)
}

func requestWithAuthentication<Model: Decodable>(_ route: Route,
Copy link
Contributor

Choose a reason for hiding this comment

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

Just to confirm: this is necessary because we're calling this as soon as we have the token; before the token has been set (since we set the token when we have the user as well)? If I'm understanding this correctly, I support this as an OK evil, especially if we still think we may get the user object returned with the token in the future.

@amy-at-kickstarter amy-at-kickstarter merged commit c45a57e into main Feb 23, 2024
5 checks passed
@amy-at-kickstarter amy-at-kickstarter deleted the feat/adyer/MBL-1214/auth-token-as-header branch February 23, 2024 15:35
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.

None yet

3 participants