Google consent screen not shown as expected

后端 未结 3 1838
眼角桃花
眼角桃花 2020-12-21 12:15

I have registered a web application at cloud.google.com. \"The OAuth 2.0 Client ID\" looks like this: \"enter

相关标签:
3条回答
  • 2020-12-21 12:38

    Thanks @svaret for trying the application.

    I have updated the application, now it is using oauth2 for Google authentication.

    Have a try.


    Solution:-

    Create a file in src/java, e.g., Google2Api.java and paste the following code(Ref# https://gist.github.com/yincrash/2465453)

    package yourPackate;
    
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import org.scribe.exceptions.OAuthException;
    import org.scribe.extractors.AccessTokenExtractor;
    import org.scribe.model.OAuthConfig;
    import org.scribe.model.OAuthConstants;
    import org.scribe.model.OAuthRequest;
    import org.scribe.model.Response;
    import org.scribe.model.Token;
    import org.scribe.model.Verb;
    import org.scribe.model.Verifier;
    import org.scribe.oauth.OAuth20ServiceImpl;
    import org.scribe.oauth.OAuthService;
    import org.scribe.utils.OAuthEncoder;
    import org.scribe.utils.Preconditions;
    
    /**
     * Google OAuth2.0 
     * Released under the same license as scribe (MIT License)
     * @author yincrash
     * 
     */
    public class Google2Api extends DefaultApi20 {
    
    private static final String AUTHORIZE_URL = "https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=%s&redirect_uri=%s";
    private static final String SCOPED_AUTHORIZE_URL = AUTHORIZE_URL + "&scope=%s";
    
    @Override
    public String getAccessTokenEndpoint() {
        return "https://accounts.google.com/o/oauth2/token";
    }
    
    @Override
    public AccessTokenExtractor getAccessTokenExtractor() {
        return new AccessTokenExtractor() {
    
            @Override
            public Token extract(String response) {
                Preconditions.checkEmptyString(response, "Response body is incorrect. Can't extract a token from an empty string");
    
                Matcher matcher = Pattern.compile("\"access_token\" : \"([^&\"]+)\"").matcher(response);
                if (matcher.find())
                {
                  String token = OAuthEncoder.decode(matcher.group(1));
                  return new Token(token, "", response);
                } 
                else
                {
                  throw new OAuthException("Response body is incorrect. Can't extract a token from this: '" + response + "'", null);
                }
            }
        };
    }
    
    @Override
    public String getAuthorizationUrl(OAuthConfig config) {
        // Append scope if present
        if (config.hasScope()) {
            return String.format(SCOPED_AUTHORIZE_URL, config.getApiKey(),
                    OAuthEncoder.encode(config.getCallback()),
                    OAuthEncoder.encode(config.getScope()));
        } else {
            return String.format(AUTHORIZE_URL, config.getApiKey(),
                    OAuthEncoder.encode(config.getCallback()));
        }
    }
    
    @Override
    public Verb getAccessTokenVerb() {
        return Verb.POST;
    }
    
    @Override
    public OAuthService createService(OAuthConfig config) {
        return new GoogleOAuth2Service(this, config);
    }
    
    private class GoogleOAuth2Service extends OAuth20ServiceImpl {
    
        private static final String GRANT_TYPE_AUTHORIZATION_CODE = "authorization_code";
        private static final String GRANT_TYPE = "grant_type";
        private DefaultApi20 api;
        private OAuthConfig config;
    
        public GoogleOAuth2Service(DefaultApi20 api, OAuthConfig config) {
            super(api, config);
            this.api = api;
            this.config = config;
        }
    
        @Override
        public Token getAccessToken(Token requestToken, Verifier verifier) {
            OAuthRequest request = new OAuthRequest(api.getAccessTokenVerb(), api.getAccessTokenEndpoint());
            switch (api.getAccessTokenVerb()) {
            case POST:
                request.addBodyParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
                request.addBodyParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
                request.addBodyParameter(OAuthConstants.CODE, verifier.getValue());
                request.addBodyParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
                request.addBodyParameter(GRANT_TYPE, GRANT_TYPE_AUTHORIZATION_CODE);
                break;
            case GET:
            default:
                request.addQuerystringParameter(OAuthConstants.CLIENT_ID, config.getApiKey());
                request.addQuerystringParameter(OAuthConstants.CLIENT_SECRET, config.getApiSecret());
                request.addQuerystringParameter(OAuthConstants.CODE, verifier.getValue());
                request.addQuerystringParameter(OAuthConstants.REDIRECT_URI, config.getCallback());
                if(config.hasScope()) request.addQuerystringParameter(OAuthConstants.SCOPE, config.getScope());
            }
            Response response = request.send();
            return api.getAccessTokenExtractor().extract(response.getBody());
        }
    }
    
    }
    

    and update google provider in Config.groovy

    ....
    google {
        api = yourPackate.Google2Api
        ...
    }
    ....
    

    Note:- Package name must not be same as scribe api, i.e., org.scribe.builder.api. Make some thing different package name. I am using org.scribe.api.

    0 讨论(0)
  • 2020-12-21 12:46

    https://github.com/manishkbharti/grailsOauthPluginDemo already update the way to use Oauth2 for google. If you can't use Oauth2 from this Demo, you can look at grails plugin: Google for Spring Security OAuth plugin (https://github.com/donbeave/grails-spring-security-oauth-google). In their source code, they try to implement Oauth2 from DefaultApi20 class

    I don't know why but I can only get the authorization code after the process, so I need to do an extra step to convert this code to an access token, here is the code in details:

    def oauth2callback = { def code = params.code

        HttpTransport transport = new NetHttpTransport();
        JacksonFactory jsonFactory = new JacksonFactory();
        String CLIENT_ID = "....";
        String CLIENT_SECRET = "....";
        String REDIRECT_URI = ".....";
    
        GoogleTokenResponse response =
            new GoogleAuthorizationCodeTokenRequest(transport, jsonFactory, CLIENT_ID, CLIENT_SECRET, code, REDIRECT_URI).execute();
    
        GoogleCredential credential = new GoogleCredential.Builder().setClientSecrets(CLIENT_ID, CLIENT_SECRET)
                .setJsonFactory(jsonFactory).setTransport(transport).build()
                .setAccessToken(response.getAccessToken()).setRefreshToken(response.getRefreshToken());
    
        SpreadsheetService service = new SpreadsheetService("MySpreadsheetIntegration-v1");
        service.setOAuth2Credentials(credential);
        // Define the URL to request.  This should never change.
        URL SPREADSHEET_FEED_URL = new URL(
                "https://spreadsheets.google.com/feeds/spreadsheets/private/full");
    
        // Make a request to the API and get all spreadsheets.
        SpreadsheetFeed feed = service.getFeed(SPREADSHEET_FEED_URL, SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheets = feed.getEntries();
    
        spreadsheets.each {
            println it.getTitle().getPlainText()
        }
    }
    
    0 讨论(0)
  • 2020-12-21 12:56

    I believe that the grailsOauthPluginDemo is using Google's OAuth1.0a API which currently uses different templates for the consent page.

    Hope that helps!

    0 讨论(0)
提交回复
热议问题