实现远程oauth服务器并与客户端交换令牌,而服务器上没有保存令牌

问题描述 投票:0回答:1

//更新-见下文

因此,我目前正在开发一个小型Java应用程序,以访问我的实时流的聊天记录。除了twitch yt之外,没有irc服务器来访问聊天,因此我被迫使用yt api。基本上我只打算自己使用它,但是我可能会为某些朋友提供它,甚至将其公开。我已经成功获得了对api的访问权限,但前提是我将客户端密码和令牌存储在系统中。当我想公开打开它时,我必须设置一个身份验证服务器,然后将令牌传递给客户端。主要问题是实际需要创建令牌的方法com.google.api.client.auth.oauth2.AuthorizationCodeFlow.createAndStoreCredential(TokenResponse,String)。这将在任何代码运行的地方存储令牌-因此,在服务器而非客户端的计划环境中。我还发现了这一点:OAuth-server, storing user tokens-因此,只要我每次使用google oauth的服务都能正确理解此内容,便会将访问令牌存储在其自己的存储中,然后有人与客户端进行交互。因此,我有两个问题:1)如果我想向公众开放一个项目,以便他人使用,该如何实现这种身份验证服务?2)如何将令牌发送给客户端?还是必须通过我的服务器完成所有通信?2a)如果上一个问题的答案是“是”,那么我该如何确保访问权限安全,以便每个客户端只能在仅由简单字符串标识的情况下才能访问其自己的令牌?

当前,这是获得令牌的代码:

public class Main
{
    public final static void main(final String... args)
    {
        (new Main()).start();
    }
    private Main() {}
    private void start()
    {
        try
        {
            File DATA_STORE_DIR=new File(System.getProperty("user.home"), "yta");
            JsonFactory JSON_FACTORY=JacksonFactory.getDefaultInstance();
            List<String> SCOPES=Arrays.asList(YouTubeScopes.YOUTUBE_READONLY, YouTubeScopes.YOUTUBE, YouTubeScopes.YOUTUBE_FORCE_SSL, YouTubeScopes.YOUTUBE_UPLOAD);
            DataStoreFactory DATA_STORE_FACTORY=new FileDataStoreFactory(DATA_STORE_DIR);
            NetHttpTransport transport=GoogleNetHttpTransport.newTrustedTransport();
            GoogleClientSecrets clientSecrets=GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(new FileInputStream(new File(DATA_STORE_DIR, "client_secret.json"))));
            GoogleAuthorizationCodeFlow googleAuthorizationCodeFlow=new GoogleAuthorizationCodeFlow.Builder(transport, JSON_FACTORY, clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).build();
            String authURL=googleAuthorizationCodeFlow.newAuthorizationUrl().setRedirectUri("urn:ietf:wg:oauth:2.0:oob").build();
            Desktop.getDesktop().browse(new URI(authURL));
            String authToken=System.console().readLine();
            GoogleTokenResponse googleTokenResponse=googleAuthorizationCodeFlow.newTokenRequest(authToken).setRedirectUri("urn:ietf:wg:oauth:2.0:oob").execute();
            Credential credential=googleAuthorizationCodeFlow.createAndStoreCredential(googleTokenResponse, "userId");
        }
        catch(IOException|GeneralSecurityException|URISyntaxException ex)
        {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}

最终将在DATA_STORE_DIR目录中创建文件“ StoredCredential”,该目录包含由“ userId”标识的身份验证令牌。要将令牌传输到客户端,我可以调用getRefreshToken和getAccessToken,将它们发送到客户端,将它们存储在客户端上,从这两个字符串构建一个新的Credential实例,并通过刷新来“激活”它。为了在服务器端摆脱令牌,我可以在数据存储区上调用delete-为了提高安全性,我可以为此流使用一个UUID,因此某些攻击者很难截获令牌-但存在风险还在那儿。因此,我正在寻找一种无需将令牌存储在服务器上(甚至不是很短的时间)来创建令牌的方法,以防止可能的攻击媒介。你们谁知道怎么做?

//更新因此,我进行了修补,以了解如何在客户端上创建令牌-仍然需要在身份验证代码流中使用我的client-id和client-secret(否则,您会收到一个异常,告诉您设置这些令牌)。最终这些行:

credential=(new Credential.Builder(BearerToken.authorizationHeaderAccessMethod()))
    .setTransport(transport)
    .setJsonFactory(JSON_FACTORY)
    .setTokenServerEncodedUrl("https://oauth2.googleapis.com/token")
    .setClientAuthentication(new ClientParametersAuthentication("client-id", "client-secret"))
    .build()
.setAccessToken("access-token")
.setRefreshToken("refresh-token");

据我所知,即使不公开api秘密,也无法将Credential对象传输到远程客户端。这意味着任何呼叫都必须通过服务器,必须通过服务器会话/连接以某种方式唯一地标识客户端,并且每个答复都必须转发回客户端。

所以-这使我想到一个问题:我想做的事*甚至可能吗?* =用java编写一个程序,以访问我的实时流聊天-将该程序的令牌存储在本地,但请求外部服务器来获取它]

我也尝试过使用API​​密钥-但对于我要执行的操作似乎没有足够的权限-甚至对于给定用户名的简单通道ID查找都失败了,所以我必须使用OAuth

//更新2好吧-没关系-我在5分钟内达到了每天10k的正常免费用户帐户的最大限制-猜猜我必须切换到抽搐然后...

//更新-见下文,因此,我目前正在开发一个小型Java应用程序,以访问我的实时直播聊天室。除了twitch yt之外,没有用于聊天的irc服务器,因此我被迫...

java google-oauth google-oauth2 google-oauth-java-client
1个回答
0
投票

所以,我找到了一个解决方案:https://github.com/cryptearth/YouTubeLiveChat/commit/b1ce15400688b6907600b006463ce538132bd807归结为直到现在我还不了解的两件事:

© www.soinside.com 2019 - 2024. All rights reserved.