Skip to content

Commit d0e848d

Browse files
committed
document the auth wrapper
Signed-off-by: Adam Ratzman <[email protected]>
1 parent 02aec1a commit d0e848d

File tree

2 files changed

+68
-10
lines changed

2 files changed

+68
-10
lines changed

src/androidMain/kotlin/com/adamratzman/spotify/auth/AbstractSpotifyLoginActivity.kt

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,50 @@ import com.adamratzman.spotify.spotifyImplicitGrantApi
1111
import com.spotify.sdk.android.auth.AuthorizationClient
1212
import com.spotify.sdk.android.auth.AuthorizationRequest
1313
import com.spotify.sdk.android.auth.AuthorizationResponse
14+
import com.spotify.sdk.android.auth.LoginActivity
1415

16+
/**
17+
* Wrapper around spotify-auth's [LoginActivity] that allows configuration of the authentication process, along with
18+
* callbacks on successful and failed authentication. Pair this with [SpotifyDefaultCredentialStore] to easily store credentials.
19+
*
20+
* @property state The state to use to verify the login request.
21+
* @property clientId Your application's Spotify client id.
22+
* @property clientId Your application's Spotify client secret.
23+
* @property redirectUri Your application's Spotify redirect id - NOTE that this should be an android scheme (such as spotifyapp://authback)
24+
* and that this must be registered in your manifest.
25+
* @property useDefaultRedirectHandler Disable if you will not be using [useDefaultRedirectHandler] but will be setting [SpotifyDefaultAuthHelper.activityBack].
26+
*
27+
*/
1528
public abstract class AbstractSpotifyLoginActivity : Activity() {
1629
public abstract val state: Int
1730
public abstract val clientId: String
1831
public abstract val redirectUri: String
19-
public abstract val useDefaultRedirectHandler: Boolean
32+
public open val useDefaultRedirectHandler: Boolean = true
33+
34+
/**
35+
* Return the scopes that you are going to request from the user here.
36+
*/
2037
public abstract fun getRequestingScopes(): List<SpotifyScope>
2138

39+
/**
40+
* Override this to define what to do after authentication has been successfully completed. A valid, usable
41+
* [spotifyApi] is provided to you. You may likely want to use [SpotifyDefaultCredentialStore] to store/retrieve this token.
42+
*
43+
* @param spotifyApi Valid, usable [SpotifyImplicitGrantApi] that you can use to make requests.
44+
*/
2245
public abstract fun onSuccessfulAuthentication(spotifyApi: SpotifyImplicitGrantApi)
46+
47+
/**
48+
* Override this to define what to do after authentication has failed. You may want to use [SpotifyDefaultCredentialStore] to remove any stored token.
49+
*/
2350
public abstract fun onAuthenticationFailed(errorMessage: String)
51+
52+
53+
/**
54+
* Override this to define what to do after [onSuccessfulAuthentication] has run.
55+
* The default behavior is to finish the activity, and redirect the user back to the activity set on [SpotifyDefaultAuthHelper.activityBack]
56+
* only if [guardValidSpotifyApi] has been used or if [SpotifyDefaultAuthHelper.activityBack] has been set.
57+
*/
2458
public open fun redirectAfterOnSuccessAuthentication() {
2559
if (useDefaultRedirectHandler && SpotifyDefaultAuthHelper.activityBack != null) {
2660
startActivity(Intent(this, SpotifyDefaultAuthHelper.activityBack))
@@ -35,15 +69,21 @@ public abstract class AbstractSpotifyLoginActivity : Activity() {
3569
triggerLoginActivity()
3670
}
3771

72+
/**
73+
* Trigger the actual spotify-auth login activity to authenticate the user.
74+
*/
3875
public fun triggerLoginActivity() {
39-
val authorizationRequest =
40-
AuthorizationRequest.Builder(clientId, AuthorizationResponse.Type.TOKEN, redirectUri)
41-
.setScopes(getRequestingScopes().map { it.uri }.toTypedArray())
42-
.setState(state.toString())
43-
.build()
76+
val authorizationRequest = AuthorizationRequest.Builder(clientId, AuthorizationResponse.Type.TOKEN, redirectUri)
77+
.setScopes(getRequestingScopes().map { it.uri }.toTypedArray())
78+
.setState(state.toString())
79+
.build()
80+
4481
AuthorizationClient.openLoginActivity(this, state, authorizationRequest)
4582
}
4683

84+
/**
85+
* Processes the result of [LoginActivity], invokes callbacks, then finishes.
86+
*/
4787
override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
4888
super.onActivityResult(requestCode, resultCode, intent)
4989
if (requestCode == state) {
@@ -58,9 +98,7 @@ public abstract class AbstractSpotifyLoginActivity : Activity() {
5898
val api = spotifyImplicitGrantApi(
5999
clientId = clientId,
60100
token = token
61-
) {
62-
refreshTokenProducer = { throw SpotifyException.ReAuthenticationNeededException() }
63-
}
101+
)
64102

65103
onSuccessfulAuthentication(api)
66104
redirectAfterOnSuccessAuthentication()

src/androidMain/kotlin/com/adamratzman/spotify/auth/AuthUtils.kt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public class SpotifyDefaultCredentialStore constructor(private val clientId: Str
107107
)
108108

109109
/**
110-
*
110+
* Get/set when the Spotify access token will expire, in milliseconds from UNIX epoch. This will be one hour from authentication.
111111
*/
112112
public var spotifyTokenExpiresAt: Long?
113113
get() {
@@ -119,10 +119,17 @@ public class SpotifyDefaultCredentialStore constructor(private val clientId: Str
119119
else encryptedPreferences.edit().putLong(SpotifyTokenExpiryKey, value).apply()
120120
}
121121

122+
/**
123+
* Get/set the Spotify access token (the access token string, not the wrapped [Token]).
124+
*/
122125
public var spotifyAccessToken: String?
123126
get() = encryptedPreferences.getString(SpotifyAccessTokenKey, null)
124127
set(value) = encryptedPreferences.edit().putString(SpotifyAccessTokenKey, value).apply()
125128

129+
/**
130+
* Get/set the Spotify [Token] obtained from [spotifyToken].
131+
* If the token has expired according to [spotifyTokenExpiresAt], this will return null.
132+
*/
126133
public var spotifyToken: Token?
127134
get() {
128135
val tokenExpiresAt = spotifyTokenExpiresAt ?: return null
@@ -141,15 +148,28 @@ public class SpotifyDefaultCredentialStore constructor(private val clientId: Str
141148
}
142149
}
143150

151+
/**
152+
* Create a new [SpotifyImplicitGrantApi] instance using the [spotifyToken] stored using this credential store.
153+
*
154+
* @param block Applied configuration to the [SpotifyImplicitGrantApi]
155+
*/
144156
public fun getSpotifyImplicitGrantApi(block: ((SpotifyApiOptions).() -> Unit)? = null): SpotifyImplicitGrantApi? {
145157
val token = spotifyToken ?: return null
146158
return spotifyImplicitGrantApi(clientId, token, block ?: {})
147159
}
148160

161+
/**
162+
* Sets [spotifyToken] using [SpotifyImplicitGrantApi.token]. This wraps around [spotifyToken]'s setter.
163+
*
164+
* @param api A valid [SpotifyImplicitGrantApi]
165+
*/
149166
public fun setSpotifyImplicitGrantApi(api: SpotifyImplicitGrantApi) {
150167
spotifyToken = api.token
151168
}
152169

170+
/**
171+
* Clear the [SharedPreferences] instance corresponding to the Spotify credentials.
172+
*/
153173
@SuppressLint("ApplySharedPref")
154174
public fun clear(): Boolean = try {
155175
encryptedPreferences.edit().clear().commit()

0 commit comments

Comments
 (0)