-
Notifications
You must be signed in to change notification settings - Fork 593
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
Add Route header classes #4562
base: auth-exchange
Are you sure you want to change the base?
Add Route header classes #4562
Changes from all commits
91d734f
7fa1d26
ea49639
6c5b902
74e6fb7
1817518
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
plugins { | ||
id("firebase-library") | ||
kotlin("android") | ||
kotlin("plugin.serialization") version "1.7.20" | ||
} | ||
|
||
firebaseLibrary { | ||
publishSources = true | ||
} | ||
|
||
android { | ||
val targetSdkVersion : Int by rootProject | ||
|
||
compileSdk = targetSdkVersion | ||
defaultConfig { | ||
minSdk = 16 | ||
targetSdk = targetSdkVersion | ||
multiDexEnabled = true | ||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
sourceSets { | ||
getByName("main") { | ||
java.srcDirs("src/main/kotlin") | ||
} | ||
getByName("test") { | ||
java.srcDirs("src/test/kotlin") | ||
} | ||
} | ||
|
||
testOptions.unitTests.isIncludeAndroidResources = true | ||
} | ||
|
||
dependencies { | ||
daymxn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
implementation(project(":firebase-common")) | ||
implementation(project(":firebase-common:ktx")) | ||
implementation(project(":firebase-components")) | ||
implementation(project(":firebase-authexchange-interop")) | ||
|
||
implementation(libs.androidx.annotation) | ||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") | ||
implementation(libs.kotlin.stdlib) | ||
|
||
|
||
testImplementation(libs.androidx.test.core) | ||
testImplementation(libs.truth) | ||
testImplementation(libs.junit) | ||
testImplementation(libs.robolectric) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package com.google.firebase.authexchange.network | ||
|
||
import kotlinx.serialization.SerialName | ||
import kotlinx.serialization.Serializable | ||
|
||
/** | ||
* Defines what an HTTP request may look like when interacting with the backend API for | ||
rlazo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* [FirebaseAuthExchange][com.google.firebase.authexchange.FirebaseAuthExchange]. | ||
*/ | ||
@Serializable internal sealed interface Request | ||
rosalyntan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** Defines what an HTTP response may look like when submitting a [Request]. */ | ||
@Serializable internal sealed interface Response | ||
|
||
/** | ||
* OIDC Credential. | ||
* | ||
* Useful for apps with external login already set-up, otherwise known as a headless OIDC flow. | ||
Comment on lines
+16
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is an OIDC credential, would it make sense to call the class that? Not sure if implicit credentials is the right naming. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would be comfortable with that, although the property name would still be I can't link it here since it's an internal link- but if you look at the bug linked in this PR (referenced in the OP), and go to the first link in the comments of that bug, you can see all the proto defs for the API. These definitions and their names are derived from that- since these are all just data classes for the API- intended to be encoded to JSON via There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I forgot we can specify a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an scenario where more details help :-) You could change the first line of the description to "Credentials returned by an OIDC implicit flow" Then the name would sound more fitting. No need to use |
||
* | ||
* @property idToken JWT encoded OIDC token returned from a third party provider | ||
*/ | ||
@Serializable internal data class ImplicitCredentialsP(val idToken: String) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Protobuf, implying that these data classes are representations of gRPC related data (that is, they're raw classes that shouldn't be used directly, and are intended to only be used by the network layer). I'm not quite sure where I picked this up from, but I've used this naming convention by habit in all of my personal gRPC projects. Helps more easily difference between the network and application layer. Although if you're against it, I'm fine with removing it:) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be consistent with the rest of our code, I'd rathe remove it. That being said, the discussion of the value and usage of suffixes in code naming is a long and interesting one for the future :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 to removing the |
||
|
||
/** | ||
* Auth Token that can be used to access certain Firebase Services. | ||
* | ||
* This is merely the proto type for the network layer, and is completely separate from the user | ||
* facing [AuthExchangeToken][com.google.firebase.authexchange.AuthExchangeToken]. | ||
* | ||
Comment on lines
+27
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what do you mean by a proto type in this case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As in it's a data class used for communicating via protobuf APIs (the backend for auth echange). Although I do think the phrasing gives off the wrong impression. Thoughts on this instead:
Or maybe just removing it entirely? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 your suggested rewording. |
||
* @property accessToken signed JWT containing claims that identify a user | ||
* @property timeToLive the duration from the time this token is minted until its expiration | ||
*/ | ||
@Serializable | ||
internal data class AuthExchangeTokenP( | ||
val accessToken: String, | ||
@SerialName("ttl") val timeToLive: String | ||
) | ||
|
||
/** | ||
* Request header for the `/ExchangeInstallationAuthToken` endpoint. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a header or the actual request? here and below There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So nothing here actually implements the requests themselves. These are all just headers, or type defs, of what the API expects. Skeletons you could say. Actual implementation and utilization of these classes will be elsewhere in the SDK. The API is currently defined in protobuf in G3, and all these classes provide a type-safe kotlin variant of the API as it is defined. Additionally, we can use kotlin's serialization, and immediately encode classes to JSON requests for the backend, and vise versa for JSON responses from the backend. Just a little quick example (psuedo code): data class GetPersonRequestP(val name: String)
data class GetPersonResponseP(val person: Person?, val error: String?)
data class Person(val name: String, age: Int, phoneNumber: String)
fun getPerson() {
val myQuery = GetPersonRequestP("Rodrigo")
val response: GetPersonResponseP = googleServer:GetRequest<GetPersonRequestP>(myQuery)
response?.person?.let {
println("Rodrigo is ${it.age} years old!")
}
} All subclasses of All subclasses of Anything else is just extra data types that either need to be arguments in a call to a certain API, or are apart of a response. Does that answer your question? Or did I misunderstand what you were asking? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All below are either There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
They contain the content sure, but only in the sense that it's a data class and doesn't have any content. I think C headers- where data types and function signatures are declared in header files, and the source file implements said methods. Although, what do you think would be a better name? We could also always just split it up into two separate files; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 to "request header" implying network request headers, for example the Though I'm not sure I understand what you mean when you say the actual implementation of these classes will exist elsewhere -- from my understanding of a Kotlin data class, it is essentially like a struct, which is fully instantiable (i.e. it's not like a Java interface where you need to implement the interface before it can be used). Also, are these data classes not implementations of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You're right on the money
Implementation was probably the wrong phrasing, I more-so meant the usage of these classes occur elsewhere- and this isn't intended to provide any logic
They are, I just meant splitting the files for naming & organization sake There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see -- in terms of naming clarity, I think you can just remove the term "header" from the documentation and leave the rest of the comment the same. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 |
||
* | ||
* @see ExchangeTokenResponseP | ||
* | ||
* @property token relative resource name of the audience project and location | ||
* @property installationAuthToken the installation token issued to the app | ||
*/ | ||
@Serializable | ||
internal data class ExchangeInstallationAuthTokenRequestP( | ||
val token: String, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh I see. Is it the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean by |
||
val installationAuthToken: String | ||
) : Request | ||
|
||
/** | ||
* Request header for the `/ExchangeCustomToken` endpoint. | ||
* | ||
* @see ExchangeTokenResponseP | ||
* | ||
* @property token relative resource name of the audience project and location | ||
* @property customToken a custom JWT token signed with the developer's credentials | ||
*/ | ||
@Serializable | ||
internal data class ExchangeCustomTokenRequestP(val token: String, val customToken: String) : | ||
Request | ||
|
||
/** | ||
* Request header for the `/ExchangeOidcToken` endpoint. | ||
* | ||
* @see ExchangeOidcTokenResponseP | ||
* | ||
* @property token relative resource name of the audience project and location | ||
* @property providerId the display name or id of the OIDC provider | ||
* @property implicitCredentials JWT token from the OIDC provider, provided by the developer | ||
*/ | ||
@Serializable | ||
internal data class ExchangeOidcTokenRequestP( | ||
val token: String, | ||
val providerId: String, | ||
val implicitCredentials: ImplicitCredentialsP | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For sure, although do we use it on our end? I initially had the following comment: /**
* While this isn't the only OIDC flow that the API supports, it's the only flow that the mobile SDK
* supports- so there is no base class for credentials.
*/ Because I was under the impression we don't utilize There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The auth code OIDC flow is the "headful" flow (detailed here). |
||
) : Request | ||
|
||
/** | ||
* Response header for endpoints that just expect an [AuthExchangeTokenP]. | ||
* | ||
* @see ExchangeCustomTokenRequestP | ||
* @see ExchangeInstallationAuthTokenRequestP | ||
* | ||
* @property token auth token returned by the backend | ||
*/ | ||
@Serializable internal data class ExchangeTokenResponseP(val token: AuthExchangeTokenP) : Response | ||
|
||
/** | ||
* Response header for the `/ExchangeOidcToken` endpoint. | ||
* | ||
* @see ExchangeOidcTokenRequestP | ||
* | ||
* @property authExchangeToken auth token returned by the backend | ||
* @property oidcIdToken OAuth id token received from the OIDC provider | ||
* @property oidcRefreshToken optional OAuth refresh token received from the OIDC provider | ||
*/ | ||
@Serializable | ||
internal data class ExchangeOidcTokenResponseP( | ||
val authExchangeToken: AuthExchangeTokenP, | ||
val oidcIdToken: String, | ||
val oidcRefreshToken: String? = null | ||
) : Response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing copyright notice here and elsewhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! I had a script I wrote that would automatically add it to any missing files, but it doesn't auto-run. We should probably have some sort of check regarding that. Not anything that's enforced, since there are way too many exceptions, but maybe like a git hook or gha that looks at files added and lets you know if any of interest are missing copyright notices (
.kt
,.java
,etc.,).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is one, and it's correctly reporting this :-)
https://github.com/firebase/firebase-android-sdk/actions/runs/3917153439
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOL, well I'll be paying more attention to that one for sure