Spring Exchange用户信息的Google访问令牌

68bkxrlz  于 5个月前  发布在  Spring
关注(0)|答案(2)|浏览(59)

我正在尝试为我的网站实现Google身份验证,它是React前端和Sping Boot REST后端。
对于我的React应用程序,我找到了一个提供Google Login按钮的库,我可以在其中指定我的应用程序的“client-id”,在Google开发人员的控制台中注册,其余的(将用户重定向到Google身份验证页面,检索访问令牌/ID令牌)由这个库完成。
现在我想把这个访问令牌发送到我的后端,用它来向谷歌发出请求,以验证这个前端用户是一个真实的谷歌用户,谁正确认证,并通过显示这个访问令牌谷歌获得这个用户的数据(我只想要电子邮件/名称/子,这是用户唯一的谷歌ID).我正在寻找一些库来交换这个谷歌访问令牌的用户数据?
我也很困惑,所有的oauth教程都说,当用户在google页面上进行身份验证时,我的应用程序将收到一个授权码,但我的前端收到的是acces token和id token。这是因为我使用的库吗?https://www.npmjs.com/package/react-google-login这是库
这是当用户在Google页面console.log(response) in browser上进行身份验证时,进入我的客户端应用程序的数据
谢谢

sh7euo9m

sh7euo9m1#

我和你有同样的问题。我通过使用谷歌的GoogleIdTokenVerifier解决了它。设置非常简单。
这是我的代码:

import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

@RestController
@RequestMapping(value = "/api/authenticate")
public final class AuthenticationController {

    @GetMapping
    public String exchange(@Autowired NetHttpTransport transport, @Autowired GsonFactory factory, HttpServletRequest request) throws GeneralSecurityException, IOException, IllegalAccessException {
        // get id_token from Authorization Bearer
        String token = this.getTokenFromRequest(request);

        // Create verifier
        GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, factory)
                .setAudience(Collections.singletonList(<CLIENT_ID_HERE>))
                .build();

        // Verify it
        GoogleIdToken idToken = verifier.verify(token);
        if (idToken == null) {
            throw new IllegalAccessException("Invalid id_token");
        }
        // Access payload 
        System.out.println("Email: " + idToken.getPayload().getEmail());
    }

    public String getTokenFromRequest(HttpServletRequest request) throws IllegalAccessException {
        String token = request.getHeader("Authorization");
        String[] parts = token.split(" ");
        if (parts.length != 2 || !parts[0].contains("Bearer")) {
            throw new IllegalAccessException("Authorization Bearer format invalid. <Bearer {token}>");
        }
        return parts[1];
    }
}

字符串
Maven依赖项:

<dependency>
    <groupId>com.google.api-client</groupId>
    <artifactId>google-api-client</artifactId>
    <version>1.30.4</version>
</dependency>

<dependency>
    <groupId>com.google.http-client</groupId>
    <artifactId>google-http-client-gson</artifactId>
    <version>1.21.0</version>
</dependency>

6uxekuva

6uxekuva2#

也许我迟到了,但让我把它留在这里:
1.您正在使用的react库故意检索访问令牌,因为它假定您将使用它作为前端,因此使用此令牌,您可以向资源服务器发出任何进一步的请求。在这种情况下,资源服务器和auth服务器是相同的。例如,你想使用谷歌作为OAuth提供者,并在你的前端应用程序中显示谷歌的联系人。所以谷歌这里是认证服务器(react的lib使Google的API调用访问令牌)和资源服务器(使用访问令牌,您的react应用程序请求Google联系人)。
1.如果后台进入游戏,您需要获得一个授权码-一个临时代码,(不是前端;它是OAuth规范中的客户端)将交换访问令牌。React向auth服务器请求auth代码(Google/Facebook/Okta)将此代码发送到后端。后端将此代码沿着client_id,secret,grant_type.和OAuth规范中定义的其他参数发送到同一个OAuth服务器。Auth服务器比较所有参数,如果所有参数都正确,则返回令牌。后端接收令牌,因此我们可以声明我们将令牌交换为代码。下一步是将令牌发送回前端,将其存储在前端,并将其附加到后端的每个后续请求中。当然,我们还需要处理刷新令牌。
这可能是一个可能的控制器方法,用于将代码交换为令牌。

@PostMapping("/check/code/google")
    public ResponseEntity<Striing> handleGoogleAuthCode(@RequestBody Map<String, String> codeMap) {
        String code = codeMap.get("code");

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        Map<String, String> params = new HashMap<>();
        params.put("code", code);
        params.put("client_id", clientId);
        params.put("client_secret", clientSecret);
        String redirectUri = "https://bpnckmnjnpoohfnodnhjpehocneckmmc.chromiumapp.org/";
        params.put("redirect_uri", redirectUri);
        params.put("grant_type", "authorization_code");

        HttpEntity<Map<String, String>> request = new HttpEntity<>(params, headers);

        ResponseEntity<Map> response = restTemplate.postForEntity("https://oauth2.googleapis.com/token", request, Map.class);
        Map<String, Object> responseBody = response.getBody();

        String accessToken = (String) responseBody.get("access_token");

       String email = profile.getEmailAddresses().get(0).getValue();
    String name = profile.getNames().get(0).getGivenName();
    try {
        // Create an Authentication Object
        SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); // "ROLE_" is a convention
        Authentication auth = new UsernamePasswordAuthenticationToken(email, null, Collections.singletonList(authority));

        // Set the Authentication Object in Security Context
        SecurityContextHolder.getContext().setAuthentication(auth);
    } catch (Exception e) {
        // Token is invalid
        SecurityContextHolder.clearContext();
    }
    JwtUtil bean = applicationContext.getBean(JwtUtil.class);
    String jwt = bean.generateSessionToken(email);
    return jwt;
    }

字符串

相关问题