1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.data.oauth;
|
---|
3 |
|
---|
4 | import java.io.ByteArrayInputStream;
|
---|
5 | import java.io.IOException;
|
---|
6 | import java.io.UncheckedIOException;
|
---|
7 | import java.nio.charset.StandardCharsets;
|
---|
8 | import java.util.Objects;
|
---|
9 |
|
---|
10 | import jakarta.json.Json;
|
---|
11 | import jakarta.json.JsonObject;
|
---|
12 | import jakarta.json.JsonObjectBuilder;
|
---|
13 | import jakarta.json.JsonReader;
|
---|
14 | import jakarta.json.JsonStructure;
|
---|
15 | import jakarta.json.JsonValue;
|
---|
16 |
|
---|
17 | import org.openstreetmap.josm.spi.preferences.Config;
|
---|
18 |
|
---|
19 | /**
|
---|
20 | * Parameters for OAuth 2.0
|
---|
21 | * @author Taylor Smock
|
---|
22 | * @since 18650
|
---|
23 | */
|
---|
24 | public final class OAuth20Parameters implements IOAuthParameters {
|
---|
25 | private static final String REDIRECT_URI = "redirect_uri";
|
---|
26 | private static final String CLIENT_ID = "client_id";
|
---|
27 | private static final String CLIENT_SECRET = "client_secret";
|
---|
28 | private static final String TOKEN_URL = "token_url";
|
---|
29 | private static final String AUTHORIZE_URL = "authorize_url";
|
---|
30 | private static final String API_URL = "api_url";
|
---|
31 | private final String redirectUri;
|
---|
32 | private final String clientSecret;
|
---|
33 | private final String clientId;
|
---|
34 | private final String tokenUrl;
|
---|
35 | private final String authorizeUrl;
|
---|
36 | private final String apiUrl;
|
---|
37 |
|
---|
38 | /**
|
---|
39 | * Recreate a parameter object from a JSON string
|
---|
40 | * @param jsonString The JSON string with the required data
|
---|
41 | */
|
---|
42 | public OAuth20Parameters(String jsonString) {
|
---|
43 | try (ByteArrayInputStream bais = new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8));
|
---|
44 | JsonReader reader = Json.createReader(bais)) {
|
---|
45 | JsonStructure structure = reader.read();
|
---|
46 | if (structure.getValueType() != JsonValue.ValueType.OBJECT) {
|
---|
47 | throw new IllegalArgumentException("Invalid JSON object: " + jsonString);
|
---|
48 | }
|
---|
49 | JsonObject jsonObject = structure.asJsonObject();
|
---|
50 | this.redirectUri = jsonObject.getString(REDIRECT_URI);
|
---|
51 | this.clientId = jsonObject.getString(CLIENT_ID);
|
---|
52 | this.clientSecret = jsonObject.getString(CLIENT_SECRET, null);
|
---|
53 | this.tokenUrl = jsonObject.getString(TOKEN_URL);
|
---|
54 | this.authorizeUrl = jsonObject.getString(AUTHORIZE_URL);
|
---|
55 | this.apiUrl = jsonObject.getString(API_URL);
|
---|
56 | } catch (IOException e) {
|
---|
57 | // This should literally never happen -- ByteArrayInputStream does not do *anything* in the close method.
|
---|
58 | throw new UncheckedIOException(e);
|
---|
59 | }
|
---|
60 | }
|
---|
61 |
|
---|
62 | /**
|
---|
63 | * Create a new OAuth parameter object
|
---|
64 | * @param clientId The client id. May not be {@code null}.
|
---|
65 | * @param clientSecret The client secret. May be {@code null}. Not currently used.
|
---|
66 | * @param baseUrl The base url. This assumes that the endpoints are {@code /token} and {@code /authorize}.
|
---|
67 | * @param apiUrl The API url
|
---|
68 | * @param redirectUri The redirect URI for the client.
|
---|
69 | */
|
---|
70 | public OAuth20Parameters(String clientId, String clientSecret, String baseUrl, String apiUrl, String redirectUri) {
|
---|
71 | this(clientId, clientSecret, baseUrl + "/token", baseUrl + "/authorize", apiUrl, redirectUri);
|
---|
72 | }
|
---|
73 |
|
---|
74 | /**
|
---|
75 | * Create a new OAuth parameter object
|
---|
76 | * @param clientId The client id.
|
---|
77 | * @param clientSecret The client secret. May be {@code null}. Not currently used.
|
---|
78 | * @param tokenUrl The token request URL (RFC6749 4.4.2)
|
---|
79 | * @param authorizeUrl The authorization request URL (RFC6749 4.1.1)
|
---|
80 | * @param apiUrl The API url
|
---|
81 | * @param redirectUri The redirect URI for the client.
|
---|
82 | */
|
---|
83 | public OAuth20Parameters(String clientId, String clientSecret, String tokenUrl, String authorizeUrl, String apiUrl, String redirectUri) {
|
---|
84 | Objects.requireNonNull(authorizeUrl, "authorizeUrl");
|
---|
85 | Objects.requireNonNull(clientId, "clientId");
|
---|
86 | Objects.requireNonNull(redirectUri, "redirectUri");
|
---|
87 | Objects.requireNonNull(tokenUrl, "tokenUrl");
|
---|
88 | Objects.requireNonNull(apiUrl, "apiUrl");
|
---|
89 | // Alternatively, we could try using rfc8414 ( /.well-known/oauth-authorization-server ), but OSM (doorkeeper) doesn't support it.
|
---|
90 | this.redirectUri = redirectUri;
|
---|
91 | this.clientId = clientId;
|
---|
92 | this.clientSecret = clientSecret;
|
---|
93 | this.tokenUrl = tokenUrl;
|
---|
94 | this.authorizeUrl = authorizeUrl;
|
---|
95 | this.apiUrl = apiUrl;
|
---|
96 | }
|
---|
97 |
|
---|
98 | @Override
|
---|
99 | public String getAccessTokenUrl() {
|
---|
100 | return this.tokenUrl;
|
---|
101 | }
|
---|
102 |
|
---|
103 | @Override
|
---|
104 | public String getAuthorizationUrl() {
|
---|
105 | return this.authorizeUrl;
|
---|
106 | }
|
---|
107 |
|
---|
108 | @Override
|
---|
109 | public OAuthVersion getOAuthVersion() {
|
---|
110 | return OAuthVersion.OAuth20;
|
---|
111 | }
|
---|
112 |
|
---|
113 | @Override
|
---|
114 | public String getClientId() {
|
---|
115 | return this.clientId;
|
---|
116 | }
|
---|
117 |
|
---|
118 | @Override
|
---|
119 | public String getClientSecret() {
|
---|
120 | return this.clientSecret;
|
---|
121 | }
|
---|
122 |
|
---|
123 | @Override
|
---|
124 | public String getRedirectUri() {
|
---|
125 | return this.redirectUri;
|
---|
126 | }
|
---|
127 |
|
---|
128 | @Override
|
---|
129 | public String getApiUrl() {
|
---|
130 | return this.apiUrl;
|
---|
131 | }
|
---|
132 |
|
---|
133 | @Override
|
---|
134 | public void rememberPreferences() {
|
---|
135 | Config.getPref().put("oauth.access-token.parameters." + OAuthVersion.OAuth20 + "." + this.apiUrl,
|
---|
136 | this.toPreferencesString());
|
---|
137 | }
|
---|
138 |
|
---|
139 | @Override
|
---|
140 | public String toPreferencesString() {
|
---|
141 | JsonObjectBuilder builder = Json.createObjectBuilder();
|
---|
142 | builder.add(CLIENT_ID, this.clientId);
|
---|
143 | builder.add(REDIRECT_URI, this.redirectUri);
|
---|
144 | if (this.apiUrl != null) builder.add(API_URL, this.apiUrl);
|
---|
145 | if (this.authorizeUrl != null) builder.add(AUTHORIZE_URL, this.authorizeUrl);
|
---|
146 | if (this.clientSecret != null) builder.add(CLIENT_SECRET, this.clientSecret);
|
---|
147 | if (this.tokenUrl != null) builder.add(TOKEN_URL, this.tokenUrl);
|
---|
148 | return builder.build().toString();
|
---|
149 | }
|
---|
150 | }
|
---|