企业API使用
场景简介
OneAccess提供第三方API的授权管理功能,API提供者将API配置到OneAccess之后,API消费者在使用API之前需要先到OneAccess获取鉴权Token,在使用API时携带该鉴权Token,API提供者根据鉴权Token判断是否可以提供服务,用以实现API的授权管理功能。
前提条件
请确保您已拥有OneAccess管理门户的访问权限。
在OneAccess中添加企业应用
在OneAccess管理门户中添加企业应用,提供给API使用者获取鉴权Token信息。
- 登录OneAccess管理门户。
- 在导航栏中,单击“资源 > 应用”。
- 在企业应用页面,单击自建应用下的“添加自建应用”,设置Logo和名称,单击“保存”。
- 获取的ClientId和ClientSecret。
在应用信息页面单击应用图标,在应用详情页面获取ClientId和ClientSecret(此信息需要提供给API使用者)。
- ClientSecret需单击“启用”生成。
- ClientSecret是校验开发者身份的密码,具备高安全性,切勿将其直接提供给第三方开发者或直接存储在代码中。
- 重置后的ClientSecret即时生效,所有使用原ClientSecret的接口将全部失效,请谨慎重置。
- OneAccess不存储ClientSecret,当获取ClientSecret后,请妥善保管。
在OneAccess中添加企业API
OneAccess管理员在OneAccess管理门户中添加企业需要的自定义API产品。
- 登录OneAccess管理门户。
- 在导航栏中,单击“资源 > 企业API”。
- 在企业API页面,单击自定义API产品下的“添加自定义API产品”。
- 在“添加企业API”页面,上传产品LOGO,填写产品名称和描述,单击“确定”,自定义API产品添加完成,自定义API产品页面显示已添加的API产品。
- 单击新建的自定义API产品,切换到“应用授权”页签,单击在OneAccess中添加企业应用中新建的应用后的“授权”,完成API对应用的授权使用。
- 切换到“权限信息”页面,添加API权限信息。
在OneAccess应用中授权相应API权限
在OneAccess的应用中,授权具体自定义API的权限。
- 登录OneAccess管理门户。
- 在导航栏中,单击“资源 > 应用”。
- 单击在OneAccess中添加企业应用中新建的应用,单击应用图标,进入通用信息页面。
- 选择“API权限 ”,在API权限页面,单击某一权限代码右侧“操作”列的“授权”则授权成功。
在OneAccess中获取签名公钥和算法密钥
OneAccess颁发的鉴权Token是经过加密和签发的,需要获取签名公钥和算法密钥给API提供者进行解密。
- 登录OneAccess管理门户。
- 在导航栏中,选择“设置 > 服务配置”,单击“API认证配置”,获取签名公钥和算法密钥,提供给API提供者。

OneAccess不展示算法密钥,当重置算法密钥后,请妥善保管。
API使用者从OneAccess获取鉴权Token
API使用者调用OneAccess鉴权接口获取鉴权Token。
访问接口:https://访问域名/api/v2/tenant/token?grant_type=client_credentials。
PostMan调用示例:

- 访问域名为用户访问域名。可在OneAccess实例详情页获取。
- 使用POST访问,使用Basic认证,Basic认证的用户名和密码为4中获取的ClientId和ClientSecret。
- 返回的id_token可以由API使用者使用对应API时传递给API提供者做身份认证和授权,其中包含签名信息以及对应的API权限信息。可以使用header来传递。建议使用标准的Authorization Header传递。
- 返回的id_token有有效期,有效期之内,此id_token可以重复使用,有效期的期限由应用中配置决定。
API提供者校验Token
API使用者调用API提供者的接口时,携带从OneAccess获取的id_token,API提供者在收到API使用者的消息时需要校验该Token,主要校验两个内容:
- Token的签名信息是否正确,保证Token是OneAccess颁发的。
- 校验Token中申明的权限是否包含当前访问当前的API。
下面是java示例代码:
import com.alibaba.fastjson.JSON;
import lombok.Data;
import org.apache.commons.codec.binary.Base64;
import org.jose4j.jwa.AlgorithmConstraints;
import org.jose4j.jwe.ContentEncryptionAlgorithmIdentifiers;
import org.jose4j.jwe.JsonWebEncryption;
import org.jose4j.jwe.KeyManagementAlgorithmIdentifiers;
import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.lang.JoseException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author : bsong
**/
public class JWTTest {
public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
public static final String END_CERT = "-----END CERTIFICATE-----";
public static void main(String[] args) throws CertificateException, InvalidJwtException, JoseException {
//id token由API调用者传递
String idToken = "";
// 算法密钥在OneAccess中设置
String aesKey = "0123******************************************789abc";
//证书在OneAccess管理门户配置中获取
String certificate = "-----BEGIN CERTIFICATE-----\n" +
"MIIC2jCCAcKgAwI..........................QEBCwUAMC4xLDAqBgNVBAMM\n" +
"I2Jzb25nLmlkYWF..........................GUuY29tMB4XDTIyMDExNDA3\n" +
"MDY1NVoXDTMyMDE..........................wwjYnNvbmcuaWRhYXMtdGVz\n" +
"dC1hbHBoYS5iY2N..........................Ib3DQEBAQUAA4IBDwAwggEK\n" +
"AoIBAQCJ7bfMCVX..........................GnE3W9uiSYk3WFkYFK8vh16\n" +
"efVuvccAULE+xqi..........................652lsIBNOAC5YPy7J47z4iw\n" +
"1GiAVYXxwyehgRe3..........................e0eJDKy6Ew5S+TUq72hqSD7\n" +
"zrtQA3szqSK1pgFB..........................J8rMh9WiF2qUqzCdNRqkQRC\n" +
"smGGj+PqD86otiif.........................0OPH5UOhR2OEve1cT9dgAlS\n" +
"Vt1tKbE0l+iUTQqi..........................oZIhvcNAQELBQADggEBAEP8\n" +
"EmkyoaWjngk3Tn5u..........................cJEDGTbuYO55wKap0BTetu6\n" +
"cvGFxJYMQYefsx0..........................xn8N4ZgWvwgwDQVQx5WPgAT\n" +
"QKunLWz30W4GYUE..........................QJZ7ift2sqoBLmkmjfcyqW0\n" +
"jU1+7/e/ea5XAC3..........................DtVHqufwP4R/TALg1muaNyJ\n" +
"f7obOcMHAb/OcbP..........................FSAwkVYsxSC9LEEUPhCONvX\n" +
"KCWoeQoX/qkZH/nBvXU=\n" +
"-----END CERTIFICATE-----";
RSAPublicKey publicKey = getPublicKeyByCertificate(certificate);
JsonWebKey jsonWebKey = getJsonWebKey(aesKey);
JwtClaims jwtClaims = validateIDToken(publicKey, idToken);
String apiPermission = jwtClaims.getClaimValue("api").toString();
String permissionString = decryptionIDToken(jsonWebKey, apiPermission);
System.out.println(permissionString);
Map<String, List<String>> permissions = getPermissionsFromIdToken(permissionString);
System.out.println(permissions);
}
public static Map<String, List<String>> getPermissionsFromIdToken(String permissionString) throws JoseException {
Map<String, List<String>> result = new HashMap<>();
Permission permission = JSON.parseObject(permissionString,Permission.class);
permission.getAuz().stream().forEach(p ->{
p.entrySet().forEach(e->{
result.put(e.getKey(),e.getValue());
});
});
return result;
}
@Data
public static class Permission{
List<Map<String, List<String>>> auth_method;
List<Map<String, List<String>>> auz;
}
public static RSAPublicKey getPublicKeyByCertificate(String certificate) throws CertificateException {
CertificateFactory fact = CertificateFactory.getInstance("X.509");
byte[] decoded = Base64.decodeBase64(certificate.replace(BEGIN_CERT, "").replace(END_CERT, ""));
InputStream input = new ByteArrayInputStream(decoded);
X509Certificate cert = (X509Certificate) fact.generateCertificate(input);
return (RSAPublicKey) cert.getPublicKey();
}
public static JsonWebKey getJsonWebKey(String key) throws JoseException {
Map<String,Object> map = new HashMap<>();
map.put("kty","oct");
map.put("k",key);
String jwkJson = JSON.toJSONString(map);
return JsonWebKey.Factory.newJwk(jwkJson);
}
public static JwtClaims validateIDToken( RSAPublicKey publicKey,String idToken) throws InvalidJwtException {
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setRequireExpirationTime() // JWT必须具有到期时间
.setAllowedClockSkewInSeconds(300) //允许在验证基于时间的声明时留有余地以解决时钟偏移
.setRequireSubject() // JWT必须具有主题声明
.setExpectedIssuer("Issuer") //谁JWT需要已被发出
.setExpectedAudience("Audience") // JWT的目标对象
.setVerificationKey(publicKey)
.build();
return jwtConsumer.processToClaims(idToken);
}
public static String decryptionIDToken(JsonWebKey jwk, String idToken) throws JoseException {
JsonWebEncryption jsonWebEncryption = new JsonWebEncryption();
jsonWebEncryption.setAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.PERMIT, KeyManagementAlgorithmIdentifiers.DIRECT));
jsonWebEncryption.setContentEncryptionAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.PERMIT, ContentEncryptionAlgorithmIdentifiers.AES_128_CBC_HMAC_SHA_256));
jsonWebEncryption.setCompactSerialization(idToken);
jsonWebEncryption.setKey(jwk.getKey());
return jsonWebEncryption.getPlaintextString();
}
}