Skip to content
This repository was archived by the owner on Mar 19, 2024. It is now read-only.

Commit e438ded

Browse files
authored
Merge pull request #367 from owncloud/feature/oidc_dynamic_client_registration
[FEATURE] OIDC Dynamic Client Registration
2 parents 3b138e7 + 37250fc commit e438ded

File tree

6 files changed

+205
-8
lines changed

6 files changed

+205
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/* ownCloud Android Library is available under MIT license
2+
*
3+
* @author Abel García de Prada
4+
*
5+
* Copyright (C) 2021 ownCloud GmbH.
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*
26+
*/
27+
28+
package com.owncloud.android.lib.resources.oauth
29+
30+
import com.owncloud.android.lib.common.OwnCloudClient
31+
import com.owncloud.android.lib.common.http.HttpConstants
32+
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod
33+
import com.owncloud.android.lib.common.operations.RemoteOperation
34+
import com.owncloud.android.lib.common.operations.RemoteOperationResult
35+
import com.owncloud.android.lib.resources.oauth.params.ClientRegistrationParams
36+
import com.owncloud.android.lib.resources.oauth.responses.ClientRegistrationResponse
37+
import com.squareup.moshi.JsonAdapter
38+
import com.squareup.moshi.Moshi
39+
import timber.log.Timber
40+
import java.net.URL
41+
42+
class RegisterClientRemoteOperation(
43+
private val clientRegistrationParams: ClientRegistrationParams
44+
) : RemoteOperation<ClientRegistrationResponse>() {
45+
46+
override fun run(client: OwnCloudClient): RemoteOperationResult<ClientRegistrationResponse> {
47+
try {
48+
val requestBody = clientRegistrationParams.toRequestBody()
49+
50+
val postMethod = PostMethod(
51+
url = URL(clientRegistrationParams.registrationEndpoint),
52+
postRequestBody = requestBody
53+
)
54+
55+
val status = client.executeHttpMethod(postMethod)
56+
57+
val responseBody = postMethod.getResponseBodyAsString()
58+
59+
if (status == HttpConstants.HTTP_CREATED && responseBody != null) {
60+
Timber.d("Successful response $responseBody")
61+
62+
// Parse the response
63+
val moshi: Moshi = Moshi.Builder().build()
64+
val jsonAdapter: JsonAdapter<ClientRegistrationResponse> =
65+
moshi.adapter(ClientRegistrationResponse::class.java)
66+
val clientRegistrationResponse: ClientRegistrationResponse? = jsonAdapter.fromJson(responseBody)
67+
Timber.d("Client registered and parsed to $clientRegistrationResponse")
68+
69+
return RemoteOperationResult<ClientRegistrationResponse>(RemoteOperationResult.ResultCode.OK).apply {
70+
data = clientRegistrationResponse
71+
}
72+
73+
} else {
74+
Timber.e("Failed response while registering a new client. Status code: $status; response message: $responseBody")
75+
return RemoteOperationResult<ClientRegistrationResponse>(postMethod)
76+
}
77+
78+
} catch (e: Exception) {
79+
Timber.e(e, "Exception while registering a new client.")
80+
return RemoteOperationResult<ClientRegistrationResponse>(e)
81+
82+
}
83+
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* ownCloud Android Library is available under MIT license
2+
*
3+
* @author Abel García de Prada
4+
*
5+
* Copyright (C) 2021 ownCloud GmbH.
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*
26+
*/
27+
package com.owncloud.android.lib.resources.oauth.params
28+
29+
import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_JSON
30+
import okhttp3.MediaType.Companion.toMediaType
31+
import okhttp3.RequestBody
32+
import okhttp3.RequestBody.Companion.toRequestBody
33+
import org.json.JSONArray
34+
import org.json.JSONObject
35+
36+
data class ClientRegistrationParams(
37+
val registrationEndpoint: String,
38+
val clientName: String,
39+
val redirectUris: List<String>,
40+
val tokenEndpointAuthMethod: String,
41+
val applicationType: String
42+
) {
43+
fun toRequestBody(): RequestBody =
44+
JSONObject().apply {
45+
put(PARAM_APPLICATION_TYPE, applicationType)
46+
put(PARAM_CLIENT_NAME, clientName)
47+
put(PARAM_REDIRECT_URIS, JSONArray(redirectUris))
48+
put(PARAM_TOKEN_ENDPOINT_AUTH_METHOD, tokenEndpointAuthMethod)
49+
}.toString().toRequestBody(CONTENT_TYPE_JSON.toMediaType())
50+
51+
companion object {
52+
private const val PARAM_APPLICATION_TYPE = "application_type"
53+
private const val PARAM_CLIENT_NAME = "client_name"
54+
private const val PARAM_TOKEN_ENDPOINT_AUTH_METHOD = "token_endpoint_auth_method"
55+
private const val PARAM_REDIRECT_URIS = "redirect_uris"
56+
}
57+
}

owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/oauth/params/TokenRequestParams.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,12 @@ sealed class TokenRequestParams(
4242
val redirectUri: String
4343
) : TokenRequestParams(tokenEndpoint, clientAuth, grantType) {
4444

45-
override fun toRequestBody(): RequestBody {
46-
return FormBody.Builder()
45+
override fun toRequestBody(): RequestBody =
46+
FormBody.Builder()
4747
.add(HttpConstants.OAUTH_HEADER_AUTHORIZATION_CODE, authorizationCode)
4848
.add(HttpConstants.OAUTH_HEADER_GRANT_TYPE, grantType)
4949
.add(HttpConstants.OAUTH_HEADER_REDIRECT_URI, redirectUri)
5050
.build()
51-
}
5251
}
5352

5453
class RefreshToken(
@@ -58,14 +57,13 @@ sealed class TokenRequestParams(
5857
val refreshToken: String? = null
5958
) : TokenRequestParams(tokenEndpoint, clientAuth, grantType) {
6059

61-
override fun toRequestBody(): RequestBody {
62-
return FormBody.Builder().apply {
60+
override fun toRequestBody(): RequestBody =
61+
FormBody.Builder().apply {
6362
add(HttpConstants.OAUTH_HEADER_GRANT_TYPE, grantType)
6463
if (!refreshToken.isNullOrBlank()) {
6564
add(HttpConstants.OAUTH_HEADER_REFRESH_TOKEN, refreshToken)
6665
}
6766
}.build()
6867

69-
}
7068
}
7169
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* ownCloud Android Library is available under MIT license
2+
*
3+
* @author Abel García de Prada
4+
*
5+
* Copyright (C) 2021 ownCloud GmbH.
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21+
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*
26+
*/
27+
package com.owncloud.android.lib.resources.oauth.responses
28+
29+
import com.squareup.moshi.Json
30+
import com.squareup.moshi.JsonClass
31+
32+
@JsonClass(generateAdapter = true)
33+
data class ClientRegistrationResponse(
34+
@Json(name = "client_id")
35+
val clientId: String,
36+
@Json(name = "client_secret")
37+
val clientSecret: String?,
38+
@Json(name = "client_id_issued_at")
39+
val clientIdIssuedAt: Int?,
40+
@Json(name = "client_secret_expires_at")
41+
val clientSecretExpiration: Int,
42+
)

owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/oauth/services/OIDCService.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* ownCloud Android Library is available under MIT license
22
*
3-
* Copyright (C) 2020 ownCloud GmbH.
3+
* Copyright (C) 2021 ownCloud GmbH.
44
*
55
* Permission is hereby granted, free of charge, to any person obtaining a copy
66
* of this software and associated documentation files (the "Software"), to deal
@@ -25,7 +25,9 @@ package com.owncloud.android.lib.resources.oauth.services
2525

2626
import com.owncloud.android.lib.common.OwnCloudClient
2727
import com.owncloud.android.lib.common.operations.RemoteOperationResult
28+
import com.owncloud.android.lib.resources.oauth.params.ClientRegistrationParams
2829
import com.owncloud.android.lib.resources.oauth.params.TokenRequestParams
30+
import com.owncloud.android.lib.resources.oauth.responses.ClientRegistrationResponse
2931
import com.owncloud.android.lib.resources.oauth.responses.OIDCDiscoveryResponse
3032
import com.owncloud.android.lib.resources.oauth.responses.TokenResponse
3133

@@ -38,4 +40,8 @@ interface OIDCService {
3840
tokenRequest: TokenRequestParams
3941
): RemoteOperationResult<TokenResponse>
4042

43+
fun registerClientWithRegistrationEndpoint(
44+
ownCloudClient: OwnCloudClient,
45+
clientRegistrationParams: ClientRegistrationParams
46+
): RemoteOperationResult<ClientRegistrationResponse>
4147
}

owncloudComLibrary/src/main/java/com/owncloud/android/lib/resources/oauth/services/implementation/OCOIDCService.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* ownCloud Android Library is available under MIT license
22
*
3-
* Copyright (C) 2020 ownCloud GmbH.
3+
* Copyright (C) 2021 ownCloud GmbH.
44
*
55
* Permission is hereby granted, free of charge, to any person obtaining a copy
66
* of this software and associated documentation files (the "Software"), to deal
@@ -26,8 +26,11 @@ package com.owncloud.android.lib.resources.oauth.services.implementation
2626
import com.owncloud.android.lib.common.OwnCloudClient
2727
import com.owncloud.android.lib.common.operations.RemoteOperationResult
2828
import com.owncloud.android.lib.resources.oauth.GetOIDCDiscoveryRemoteOperation
29+
import com.owncloud.android.lib.resources.oauth.RegisterClientRemoteOperation
2930
import com.owncloud.android.lib.resources.oauth.TokenRequestRemoteOperation
31+
import com.owncloud.android.lib.resources.oauth.params.ClientRegistrationParams
3032
import com.owncloud.android.lib.resources.oauth.params.TokenRequestParams
33+
import com.owncloud.android.lib.resources.oauth.responses.ClientRegistrationResponse
3134
import com.owncloud.android.lib.resources.oauth.responses.OIDCDiscoveryResponse
3235
import com.owncloud.android.lib.resources.oauth.responses.TokenResponse
3336
import com.owncloud.android.lib.resources.oauth.services.OIDCService
@@ -45,4 +48,10 @@ class OCOIDCService : OIDCService {
4548
): RemoteOperationResult<TokenResponse> =
4649
TokenRequestRemoteOperation(tokenRequest).execute(ownCloudClient)
4750

51+
override fun registerClientWithRegistrationEndpoint(
52+
ownCloudClient: OwnCloudClient,
53+
clientRegistrationParams: ClientRegistrationParams
54+
): RemoteOperationResult<ClientRegistrationResponse> =
55+
RegisterClientRemoteOperation(clientRegistrationParams).execute(ownCloudClient)
56+
4857
}

0 commit comments

Comments
 (0)