Skip to content

Commit

Permalink
fix: improve custom exception handling and update docs (#18)
Browse files Browse the repository at this point in the history
Signed-off-by: Yixiang Zhao <[email protected]>
  • Loading branch information
seriouszyx authored Feb 9, 2022
1 parent bab83d6 commit 1f9ffdc
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 62 deletions.
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ Initialization requires 5 parameters, which are all string type:
| Name (in order) | Must | Description |
| ---------------- | ---- | --------------------------------------------------- |
| endpoint | Yes | Casdoor Server Url, such as `http://localhost:8000` |
| clientId | Yes | Application.client_id |
| clientSecret | Yes | Application.client_secret |
| jwtSecret | Yes | Same as Casdoor JWT secret. |
| organizationName | Yes | Application.organization |

```go
CasdoorConfig casdoorConfig = new CasdoorConfig(endpoint, clientId, clientSecret, jwtSecret, organizationName);
| clientId | Yes | Client ID for the Casdoor application |
| clientSecret | Yes | Client secret for the Casdoor application |
| jwtPublicKey | Yes | The public key for the Casdoor application's cert |
| organizationName | Yes | The name for the Casdoor organization |
| applicationName | No | The name for the Casdoor application |

```java
CasdoorConfig casdoorConfig = new CasdoorConfig(endpoint, clientId, clientSecret, jwtPublicKey, organizationName, applicationName);
```

## Step2. Get Service and use
Expand Down Expand Up @@ -56,18 +57,19 @@ Your web application can get the `code`,`state` and call `GetOAuthToken(code, st

The general process is as follows:

```go
token = casdoorAuthService.getOAuthToken(code, state)
```java
String token = casdoorAuthService.getOAuthToken(code, state);

casdoorUser = casdoorAuthService.parseJwtToken(token)
CasdoorUser casdoorUser = casdoorAuthService.parseJwtToken(token);
```

2. **Set Session in your app**

`casdoorUser` contains the basic information about the user provided by casdoor, you can use it as a keyword to set the session in your application, like this:

```go
req.getSession.setAttribute("user", casdoorUser)
```java
HttpSession session = request.getSession();
session.setAttribute("user", user);
```

## SpringBoot Support
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2021 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package org.casbin.casdoor.exception;

/**
* @author Yixiang Zhao (@seriouszyx)
**/
public class CasdoorAuthException extends CasdoorException {
public CasdoorAuthException() {
super();
}

public CasdoorAuthException(String message, Throwable cause) {
super(message, cause);
}

public CasdoorAuthException(String message) {
super(message);
}

public CasdoorAuthException(Throwable cause) {
super(cause);
}
}
23 changes: 16 additions & 7 deletions src/main/java/org/casbin/casdoor/exception/CasdoorException.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,23 @@

package org.casbin.casdoor.exception;

public class CasdoorException extends Exception {
/**
* @author Yixiang Zhao (@seriouszyx)
*/
public class CasdoorException extends RuntimeException {
public CasdoorException() {
super();
}

public CasdoorException(String message, Throwable cause) {
super(message, cause);
}

public static CasdoorException NETWORK_EXCEPTION = new CasdoorException("Connection timeout.");
public static CasdoorException ENDPOINT_EXCEPTION = new CasdoorException("Unknown response data structure from endpoint. Please check whether the endpoint is a Casdoor instance, and is the same version of the SDK.");
public static CasdoorException PARSE_JWT_TOKEN_EXCEPTION = new CasdoorException("Cannot parse jwt token.");
public static CasdoorException VERIFY_JWT_PUBLIC_KEY_EXCEPTION = new CasdoorException("Cannot verify signature.");
public CasdoorException(String message) {
super(message);
}

private CasdoorException(String reason) {
super(reason);
public CasdoorException(Throwable cause) {
super(cause);
}
}
77 changes: 44 additions & 33 deletions src/main/java/org/casbin/casdoor/service/CasdoorAuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.casbin.casdoor.config.CasdoorConfig;
import org.casbin.casdoor.entity.CasdoorUser;
import org.casbin.casdoor.exception.CasdoorException;
import org.casbin.casdoor.exception.CasdoorAuthException;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
Expand All @@ -50,30 +50,33 @@ public CasdoorAuthService(CasdoorConfig casdoorConfig){
this.casdoorConfig = casdoorConfig;
}

public String getOAuthToken(String code, String state) throws OAuthSystemException, OAuthProblemException {
OAuthClientRequest oAuthClientRequest =
OAuthClientRequest
.tokenLocation(String.format("%s/api/login/oauth/access_token", casdoorConfig.getEndpoint()))
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setClientId(casdoorConfig.getClientId())
.setClientSecret(casdoorConfig.getClientSecret())
.setRedirectURI(String.format("%s/api/login/oauth/authorize", casdoorConfig.getEndpoint()))
.setCode(code)
.buildQueryMessage();
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
OAuthJSONAccessTokenResponse oAuthResponse = oAuthClient.accessToken(oAuthClientRequest, OAuth.HttpMethod.POST);
return oAuthResponse.getAccessToken();
public String getOAuthToken(String code, String state) {
try {
OAuthClientRequest oAuthClientRequest = OAuthClientRequest
.tokenLocation(String.format("%s/api/login/oauth/access_token", casdoorConfig.getEndpoint()))
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setClientId(casdoorConfig.getClientId())
.setClientSecret(casdoorConfig.getClientSecret())
.setRedirectURI(String.format("%s/api/login/oauth/authorize", casdoorConfig.getEndpoint()))
.setCode(code)
.buildQueryMessage();
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
OAuthJSONAccessTokenResponse oAuthResponse = oAuthClient.accessToken(oAuthClientRequest, OAuth.HttpMethod.POST);
return oAuthResponse.getAccessToken();
} catch (OAuthSystemException | OAuthProblemException e) {
throw new CasdoorAuthException("Cannot get OAuth token.", e);
}
}

public CasdoorUser parseJwtToken(String token) throws CasdoorException, InvocationTargetException, IllegalAccessException {
public CasdoorUser parseJwtToken(String token) {
// parse jwt token
SignedJWT parseJWT = null;
SignedJWT parseJwt = null;
Map<String, Object> claims = null;
try {
parseJWT = SignedJWT.parse(token);
claims = parseJWT.getJWTClaimsSet().getClaims();
parseJwt = SignedJWT.parse(token);
claims = parseJwt.getJWTClaimsSet().getClaims();
} catch (ParseException e) {
throw CasdoorException.PARSE_JWT_TOKEN_EXCEPTION;
throw new CasdoorAuthException("Cannot parse jwt token.", e);
}

// verify the jwt public key
Expand All @@ -82,38 +85,46 @@ public CasdoorUser parseJwtToken(String token) throws CasdoorException, Invocati
X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(casdoorConfig.getJwtPublicKey().getBytes()));
RSAPublicKey publicKey = (RSAPublicKey) cert.getPublicKey();
JWSVerifier verifier = new RSASSAVerifier(publicKey);
boolean verify = parseJWT.verify(verifier);
boolean verify = parseJwt.verify(verifier);
if (!verify) {
throw CasdoorException.VERIFY_JWT_PUBLIC_KEY_EXCEPTION;
throw new CasdoorAuthException("Cannot verify signature.");
}
} catch (CertificateException | JOSEException e) {
throw CasdoorException.VERIFY_JWT_PUBLIC_KEY_EXCEPTION;
throw new CasdoorAuthException("Cannot verify signature.", e);
}

// convert to CasdoorUser
CasdoorUser casdoorUser = new CasdoorUser();
BeanUtils.copyProperties(casdoorUser, claims);
return casdoorUser;
try {
CasdoorUser casdoorUser = new CasdoorUser();
BeanUtils.copyProperties(casdoorUser, claims);
return casdoorUser;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new CasdoorAuthException("Cannot convert claims to CasdoorUser", e);
}
}

public String getSigninUrl(String redirectUrl) throws UnsupportedEncodingException {
public String getSigninUrl(String redirectUrl) {
String scope = "read";
String state = casdoorConfig.getApplicationName();
return String.format("%s/login/oauth/authorize?client_id=%s&response_type=code&redirect_uri=%s&scope=%s&state=%s",
casdoorConfig.getEndpoint(), casdoorConfig.getClientId(),
URLEncoder.encode(redirectUrl, StandardCharsets.UTF_8.toString()),
scope, state);
try {
return String.format("%s/login/oauth/authorize?client_id=%s&response_type=code&redirect_uri=%s&scope=%s&state=%s",
casdoorConfig.getEndpoint(), casdoorConfig.getClientId(),
URLEncoder.encode(redirectUrl, StandardCharsets.UTF_8.toString()),
scope, state);
} catch (UnsupportedEncodingException e) {
throw new CasdoorAuthException(e);
}
}

public String getSignupUrl() throws UnsupportedEncodingException {
public String getSignupUrl() {
return getSignupUrl(true, "");
}

public String getSignupUrl(String redirectUrl) throws UnsupportedEncodingException {
public String getSignupUrl(String redirectUrl) {
return getSignupUrl(false, redirectUrl);
}

private String getSignupUrl(boolean enablePassword, String redirectUrl) throws UnsupportedEncodingException {
private String getSignupUrl(boolean enablePassword, String redirectUrl) {
if (enablePassword) {
return String.format("%s/signup/%s", casdoorConfig.getEndpoint(), casdoorConfig.getApplicationName());
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class CasdoorEmailService {
private final CasdoorConfig casdoorConfig;
final private ObjectMapper objectMapper = new ObjectMapper();

public CasdoorEmailService(CasdoorConfig casdoorConfig){
public CasdoorEmailService(CasdoorConfig casdoorConfig) {
this.casdoorConfig = casdoorConfig;
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/org/casbin/casdoor/service/CasdoorUserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ public CasdoorUserService(CasdoorConfig casdoorConfig) {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}

public CasdoorUser[] getUsers() throws Exception {
public CasdoorUser[] getUsers() throws IOException {
String targetUrl = String.format("%s/api/get-users?owner=%s&clientId=%s&clientSecret=%s",
casdoorConfig.getEndpoint(), casdoorConfig.getOrganizationName(),
casdoorConfig.getClientId(), casdoorConfig.getClientSecret());
String response = getUserResponse(targetUrl);
return objectMapper.readValue(response, CasdoorUser[].class);
}

public CasdoorUser[] getSortedUsers(String sorter, int limit) throws Exception {
public CasdoorUser[] getSortedUsers(String sorter, int limit) throws IOException {
String targetUrl = String.format("%s/api/get-sorted-users?owner=%s&clientId=%s&clientSecret=%s&sorter=%s&limit=%s",
casdoorConfig.getEndpoint(), casdoorConfig.getOrganizationName(),
casdoorConfig.getClientId(), casdoorConfig.getClientSecret(),
Expand All @@ -51,7 +51,7 @@ public CasdoorUser[] getSortedUsers(String sorter, int limit) throws Exception {
return objectMapper.readValue(response, CasdoorUser[].class);
}

public int getUserCount(String isOnline) throws Exception {
public int getUserCount(String isOnline) throws IOException {
String targetUrl = String.format("%s/api/get-user-count?owner=%s&clientId=%s&clientSecret=%s&isOnline=%s",
casdoorConfig.getEndpoint(), casdoorConfig.getOrganizationName(),
casdoorConfig.getClientId(), casdoorConfig.getClientSecret(),
Expand All @@ -60,15 +60,15 @@ public int getUserCount(String isOnline) throws Exception {
return objectMapper.readValue(response, Integer.class);
}

public CasdoorUser getUser(String name) throws Exception {
public CasdoorUser getUser(String name) throws IOException {
String targetUrl = String.format("%s/api/get-user?id=%s/%s&clientId=%s&clientSecret=%s",
casdoorConfig.getEndpoint(), casdoorConfig.getOrganizationName(), name,
casdoorConfig.getClientId(), casdoorConfig.getClientSecret());
String response = getUserResponse(targetUrl);
return objectMapper.readValue(response, CasdoorUser.class);
}

public CasdoorUser getUserByEmail(String email) throws Exception {
public CasdoorUser getUserByEmail(String email) throws IOException {
String targetUrl = String.format("%s/api/get-user?owner=%s&clientId=%s&clientSecret=%s&email=%s",
casdoorConfig.getEndpoint(), casdoorConfig.getOrganizationName(),
casdoorConfig.getClientId(), casdoorConfig.getClientSecret(),
Expand All @@ -77,9 +77,9 @@ public CasdoorUser getUserByEmail(String email) throws Exception {
return objectMapper.readValue(response, CasdoorUser.class);
}

private String getUserResponse(String targetUrl) throws Exception {
private String getUserResponse(String targetUrl) throws IOException {
String response = HttpClient.syncGet(targetUrl);
if (response == null) throw CasdoorException.NETWORK_EXCEPTION;
if (response == null) throw new CasdoorException("Connection timeout.");
return response;
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/casbin/casdoor/util/http/HttpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
public class HttpClient {
private static final OkHttpClient okHttpClient = new OkHttpClient();

public static String syncGet(String url) throws Exception{
public static String syncGet(String url) throws IOException {
Request request = new Request.Builder().url(url).build();
Response casdoorResponse = okHttpClient.newCall(request).execute();
if (casdoorResponse.isSuccessful()) {
Expand All @@ -34,7 +34,7 @@ public static String syncGet(String url) throws Exception{
public static String postString(String url, String objStr) throws IOException {
MediaType MEDIA_TYPE = MediaType.parse("text/plain;charset=UTF-8");
Request request = new Request.Builder().url(url)
.post(RequestBody.create(MEDIA_TYPE,objStr)).build();
.post(RequestBody.create(MEDIA_TYPE, objStr)).build();
Response response = okHttpClient.newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
Expand Down

0 comments on commit 1f9ffdc

Please sign in to comment.