Skip to content

Commit bf3bc70

Browse files
authored
Merge branch 'main' into layout-component
2 parents bb5cefd + 14d26d5 commit bf3bc70

File tree

12 files changed

+240
-19
lines changed

12 files changed

+240
-19
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.lowcoder.sdk.auth;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonView;
5+
import lombok.Getter;
6+
import org.apache.commons.lang3.StringUtils;
7+
import org.lowcoder.sdk.auth.constants.AuthTypeConstants;
8+
import org.lowcoder.sdk.auth.constants.Oauth2Constants;
9+
import org.lowcoder.sdk.config.SerializeConfig.JsonViews;
10+
11+
import javax.annotation.Nullable;
12+
import java.util.function.Function;
13+
14+
import static org.lowcoder.sdk.auth.constants.Oauth2Constants.CLIENT_ID_PLACEHOLDER;
15+
import static org.lowcoder.sdk.auth.constants.Oauth2Constants.INSTANCE_ID_PLACEHOLDER;
16+
17+
/**
18+
* OAuth2 ORY auth config.
19+
*/
20+
@Getter
21+
public class Oauth2OryAuthConfig extends Oauth2SimpleAuthConfig {
22+
23+
protected String instanceId;
24+
25+
@JsonCreator
26+
public Oauth2OryAuthConfig(
27+
@Nullable String id,
28+
Boolean enable,
29+
Boolean enableRegister,
30+
String source,
31+
String sourceName,
32+
String clientId,
33+
String clientSecret,
34+
String instanceId,
35+
String authType) {
36+
super(id, enable, enableRegister, source, sourceName, clientId, clientSecret, authType);
37+
this.instanceId = instanceId;
38+
}
39+
40+
@Override
41+
public String replaceAuthUrlClientIdPlaceholder(String url) {
42+
return super.replaceAuthUrlClientIdPlaceholder(url).replace(INSTANCE_ID_PLACEHOLDER, instanceId);
43+
}
44+
}

server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/auth/Oauth2SimpleAuthConfig.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public String getAuthorizeUrl() {
5252
return switch (authType) {
5353
case AuthTypeConstants.GOOGLE -> replaceAuthUrlClientIdPlaceholder(Oauth2Constants.GOOGLE_AUTHORIZE_URL);
5454
case AuthTypeConstants.GITHUB -> replaceAuthUrlClientIdPlaceholder(Oauth2Constants.GITHUB_AUTHORIZE_URL);
55+
case AuthTypeConstants.ORY -> replaceAuthUrlClientIdPlaceholder(Oauth2Constants.ORY_AUTHORIZE_URL);
5556
default -> null;
5657
};
5758
}
@@ -73,7 +74,7 @@ public void merge(AbstractAuthConfig oldConfig) {
7374
}
7475
}
7576

76-
private String replaceAuthUrlClientIdPlaceholder(String url) {
77+
public String replaceAuthUrlClientIdPlaceholder(String url) {
7778
return url.replace(CLIENT_ID_PLACEHOLDER, clientId);
7879
}
7980
}

server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/auth/constants/AuthTypeConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ public class AuthTypeConstants {
88
public static final String FORM = "FORM";
99
public static final String GOOGLE = "GOOGLE";
1010
public static final String GITHUB = "GITHUB";
11+
public static final String ORY = "ORY";
1112
}

server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/auth/constants/Oauth2Constants.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ public class Oauth2Constants {
77
public static final String REDIRECT_URL_PLACEHOLDER = "$REDIRECT_URL";
88
public static final String STATE_PLACEHOLDER = "$STATE";
99

10+
public static final String INSTANCE_ID_PLACEHOLDER = "INSTANCE_ID";
11+
1012
// authorize url
1113
public static final String GITHUB_AUTHORIZE_URL = "https://github.com/login/oauth/authorize"
1214
+ "?response_type=code"
@@ -23,4 +25,11 @@ public class Oauth2Constants {
2325
+ "&access_type=offline"
2426
+ "&scope=openid email profile"
2527
+ "&prompt=select_account";
28+
29+
public static final String ORY_AUTHORIZE_URL = "https://" + INSTANCE_ID_PLACEHOLDER + "/oauth2/auth"
30+
+ "?response_type=code"
31+
+ "&client_id=" + CLIENT_ID_PLACEHOLDER
32+
+ "&redirect_uri=" + REDIRECT_URL_PLACEHOLDER
33+
+ "&state=" + STATE_PLACEHOLDER
34+
+ "&scope=openid email profile offline_access";
2635
}

server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/constants/AuthSourceConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ public class AuthSourceConstants {
1010
public static final String PHONE = "PHONE";
1111
public static final String GOOGLE = "GOOGLE";
1212
public static final String GITHUB = "GITHUB";
13+
public static final String ORY = "ORY";
1314

1415
// source name
1516
public static final String GOOGLE_NAME = "Google";
1617
public static final String GITHUB_NAME = "Github";
18+
public static final String ORY_NAME = "Ory";
1719

1820
// default source and source name for common protocol
1921
// oauth 2.0

server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/util/JsonUtils.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package org.lowcoder.sdk.util;
22

3-
import static org.lowcoder.sdk.auth.constants.AuthTypeConstants.FORM;
4-
import static org.lowcoder.sdk.auth.constants.AuthTypeConstants.GITHUB;
5-
import static org.lowcoder.sdk.auth.constants.AuthTypeConstants.GOOGLE;
6-
73
import java.nio.charset.StandardCharsets;
84
import java.util.List;
95
import java.util.Map;
@@ -12,6 +8,7 @@
128
import javax.annotation.Nullable;
139

1410
import org.lowcoder.sdk.auth.EmailAuthConfig;
11+
import org.lowcoder.sdk.auth.Oauth2OryAuthConfig;
1512
import org.lowcoder.sdk.auth.Oauth2SimpleAuthConfig;
1613

1714
import com.fasterxml.jackson.annotation.JsonCreator;
@@ -32,6 +29,8 @@
3229

3330
import lombok.extern.slf4j.Slf4j;
3431

32+
import static org.lowcoder.sdk.auth.constants.AuthTypeConstants.*;
33+
3534
@Slf4j
3635
public final class JsonUtils {
3736

@@ -46,6 +45,7 @@ public final class JsonUtils {
4645
OBJECT_MAPPER.registerSubtypes(new NamedType(EmailAuthConfig.class, FORM));
4746
OBJECT_MAPPER.registerSubtypes(new NamedType(Oauth2SimpleAuthConfig.class, GITHUB));
4847
OBJECT_MAPPER.registerSubtypes(new NamedType(Oauth2SimpleAuthConfig.class, GOOGLE));
48+
OBJECT_MAPPER.registerSubtypes(new NamedType(Oauth2OryAuthConfig.class, ORY));
4949
}
5050

5151
public static final JsonNode EMPTY_JSON_NODE = createObjectNode();

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/dto/AuthConfigRequest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ public boolean isEnableRegister() {
2828
return MapUtils.getBoolean(this, "enableRegister", true);
2929
}
3030

31+
@Nullable
32+
public String getInstanceId() {
33+
return getString("instanceId");
34+
}
35+
3136
@Nullable
3237
public String getClientId() {
3338
return getString("clientId");

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/request/oauth2/Oauth2AuthRequestFactory.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
package org.lowcoder.api.authentication.request.oauth2;
22

3-
import static org.lowcoder.sdk.auth.constants.AuthTypeConstants.GITHUB;
4-
import static org.lowcoder.sdk.auth.constants.AuthTypeConstants.GOOGLE;
5-
63
import java.util.Set;
74

85
import org.lowcoder.api.authentication.request.AuthRequest;
96
import org.lowcoder.api.authentication.request.AuthRequestFactory;
107
import org.lowcoder.api.authentication.request.oauth2.request.AbstractOauth2Request;
118
import org.lowcoder.api.authentication.request.oauth2.request.GithubRequest;
129
import org.lowcoder.api.authentication.request.oauth2.request.GoogleRequest;
10+
import org.lowcoder.api.authentication.request.oauth2.request.OryRequest;
11+
import org.lowcoder.sdk.auth.Oauth2OryAuthConfig;
1312
import org.lowcoder.sdk.auth.Oauth2SimpleAuthConfig;
1413
import org.springframework.stereotype.Component;
1514

1615
import reactor.core.publisher.Mono;
1716

17+
import static org.lowcoder.sdk.auth.constants.AuthTypeConstants.*;
18+
1819
@Component
1920
public class Oauth2AuthRequestFactory implements AuthRequestFactory<OAuth2RequestContext> {
2021

@@ -27,6 +28,7 @@ private AbstractOauth2Request<? extends Oauth2SimpleAuthConfig> buildRequest(OAu
2728
return switch (context.getAuthConfig().getAuthType()) {
2829
case GITHUB -> new GithubRequest((Oauth2SimpleAuthConfig) context.getAuthConfig());
2930
case GOOGLE -> new GoogleRequest((Oauth2SimpleAuthConfig) context.getAuthConfig());
31+
case ORY -> new OryRequest((Oauth2OryAuthConfig) context.getAuthConfig());
3032
default -> throw new UnsupportedOperationException(context.getAuthConfig().getAuthType());
3133
};
3234
}
@@ -35,6 +37,7 @@ private AbstractOauth2Request<? extends Oauth2SimpleAuthConfig> buildRequest(OAu
3537
public Set<String> supportedAuthTypes() {
3638
return Set.of(
3739
GITHUB,
38-
GOOGLE);
40+
GOOGLE,
41+
ORY);
3942
}
4043
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/authentication/request/oauth2/Oauth2DefaultSource.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.lowcoder.api.authentication.request.oauth2;
22

3+
import org.lowcoder.sdk.auth.constants.Oauth2Constants;
4+
35
public enum Oauth2DefaultSource implements Oauth2Source {
46

57
GITHUB {
@@ -35,5 +37,23 @@ public String refresh() {
3537
return "https://www.googleapis.com/oauth2/v4/token";
3638
}
3739

40+
},
41+
42+
ORY {
43+
@Override
44+
public String accessToken() {
45+
return "https://" + Oauth2Constants.INSTANCE_ID_PLACEHOLDER + "/oauth2/token";
46+
}
47+
48+
@Override
49+
public String userInfo() {
50+
return "https://" + Oauth2Constants.INSTANCE_ID_PLACEHOLDER + "/userinfo";
51+
}
52+
53+
@Override
54+
public String refresh() {
55+
return "https://" + Oauth2Constants.INSTANCE_ID_PLACEHOLDER + "/oauth2/token";
56+
}
57+
3858
}
3959
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package org.lowcoder.api.authentication.request.oauth2.request;
2+
3+
import org.apache.commons.collections4.MapUtils;
4+
import org.apache.http.client.utils.URIBuilder;
5+
import org.lowcoder.api.authentication.request.AuthException;
6+
import org.lowcoder.api.authentication.request.oauth2.OAuth2RequestContext;
7+
import org.lowcoder.api.authentication.request.oauth2.Oauth2DefaultSource;
8+
import org.lowcoder.domain.user.model.AuthToken;
9+
import org.lowcoder.domain.user.model.AuthUser;
10+
import org.lowcoder.sdk.auth.Oauth2OryAuthConfig;
11+
import org.lowcoder.sdk.util.JsonUtils;
12+
import org.lowcoder.sdk.webclient.WebClientBuildHelper;
13+
import org.springframework.core.ParameterizedTypeReference;
14+
import org.springframework.http.MediaType;
15+
import reactor.core.publisher.Mono;
16+
17+
import java.net.URI;
18+
import java.net.URISyntaxException;
19+
import java.util.Map;
20+
21+
import static org.springframework.web.reactive.function.BodyInserters.fromFormData;
22+
23+
public class OryRequest extends AbstractOauth2Request<Oauth2OryAuthConfig> {
24+
25+
public OryRequest(Oauth2OryAuthConfig config) {
26+
super(config, Oauth2DefaultSource.ORY);
27+
}
28+
29+
@Override
30+
protected Mono<AuthToken> getAuthToken(OAuth2RequestContext context) {
31+
URI uri;
32+
try {
33+
uri = new URIBuilder(config.replaceAuthUrlClientIdPlaceholder(source.accessToken())).build();
34+
} catch (URISyntaxException e) {
35+
throw new RuntimeException(e);
36+
}
37+
38+
return WebClientBuildHelper.builder()
39+
.systemProxy()
40+
.build()
41+
.post()
42+
.uri(uri)
43+
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
44+
.body(fromFormData("code", context.getCode())
45+
.with("client_id", config.getClientId())
46+
.with("client_secret", config.getClientSecret())
47+
.with("grant_type", "authorization_code")
48+
.with("redirect_uri", context.getRedirectUrl()))
49+
.exchangeToMono(response -> response.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
50+
}))
51+
.flatMap(map -> {
52+
if (map.containsKey("error") || map.containsKey("error_description")) {
53+
throw new AuthException(JsonUtils.toJson(map));
54+
}
55+
AuthToken authToken = AuthToken.builder()
56+
.accessToken(MapUtils.getString(map, "access_token"))
57+
.expireIn(MapUtils.getIntValue(map, "expires_in"))
58+
.refreshToken(MapUtils.getString(map, "refresh_token"))
59+
.build();
60+
return Mono.just(authToken);
61+
});
62+
}
63+
64+
@Override
65+
protected Mono<AuthToken> refreshAuthToken(String refreshToken) {
66+
67+
URI uri;
68+
try {
69+
uri = new URIBuilder(config.replaceAuthUrlClientIdPlaceholder(source.refresh())).build();
70+
} catch (URISyntaxException e) {
71+
throw new RuntimeException(e);
72+
}
73+
74+
return WebClientBuildHelper.builder()
75+
.systemProxy()
76+
.build()
77+
.post()
78+
.uri(uri)
79+
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
80+
.body(fromFormData("refresh_token", refreshToken)
81+
.with("client_id", config.getClientId())
82+
.with("client_secret", config.getClientSecret())
83+
.with("grant_type", "refresh_token"))
84+
.exchangeToMono(response -> response.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
85+
}))
86+
.flatMap(map -> {
87+
if (map.containsKey("error") || map.containsKey("error_description")) {
88+
throw new AuthException(JsonUtils.toJson(map));
89+
}
90+
AuthToken authToken = AuthToken.builder()
91+
.accessToken(MapUtils.getString(map, "access_token"))
92+
.expireIn(MapUtils.getIntValue(map, "expires_in"))
93+
.refreshToken(MapUtils.getString(map, "refresh_token"))
94+
.build();
95+
return Mono.just(authToken);
96+
});
97+
98+
}
99+
100+
@Override
101+
protected Mono<AuthUser> getAuthUser(AuthToken authToken) {
102+
return WebClientBuildHelper.builder()
103+
.systemProxy()
104+
.build()
105+
.post()
106+
.uri(config.replaceAuthUrlClientIdPlaceholder(source.userInfo()))
107+
.header("Authorization", "Bearer " + authToken.getAccessToken())
108+
.exchangeToMono(response -> response.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
109+
}))
110+
.flatMap(map -> {
111+
if (map.containsKey("error") || map.containsKey("error_description")) {
112+
throw new AuthException(JsonUtils.toJson(map));
113+
}
114+
AuthUser authUser = AuthUser.builder()
115+
.uid(MapUtils.getString(map, "sub"))
116+
.username(MapUtils.getString(map, "name"))
117+
.avatar(MapUtils.getString(map, "picture"))
118+
.rawUserInfo(map)
119+
.build();
120+
return Mono.just(authUser);
121+
});
122+
}
123+
}

0 commit comments

Comments
 (0)