2017-03-27 1 views
0

Ich füge Google Register/Sign in meine Web App und ich habe ein Problem festgestellt.Java Web GoogleSignin - GoogleIdTokenVerifier Verify-Token-String gibt null zurück

Dies ist mein Code:

private static final HttpTransport transport = new NetHttpTransport(); 
private static final JsonFactory jsonFactory = new JacksonFactory(); 
private static final String MY_APP_GOOGLE_CLIENT_ID = "wouldntyouliketoknow"; 

public UsernamePasswordAuthenticationToken verify(final String idTokenString){ 

    GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) 
              .setAudience(Collections.singletonList(MY_APP_GOOGLE_CLIENT_ID)) 
              .build(); 

    try { 
     GoogleIdToken idToken = verifier.verify(idTokenString);// <-- verifier.verify returns null !!! 
     if (idToken != null) { 
      Payload payload = idToken.getPayload(); 
      String email = payload.getEmail(); 
      if(Boolean.valueOf(payload.getEmailVerified())){ 
       UserJPA jpa = userRepository.findByEmail(email); 
       if(jpa==null){ 
        throw new UsernameNotFoundException("Cannot find user with email = "+email); 
       } 
       if(!jpa.isRegisterredWithGoogle()){ 
        throw new UsernameNotFoundException("This user did not use the 'Register with google' option."); 
       } 
       bokiAuthenticationProvider.checkUserActiveAndUnlocked(jpa); 

       return new UsernamePasswordAuthenticationToken(jpa.getUsername(), jpa.getPasswordHesh(), 
         bokiAuthenticationProvider.getAuthorities(jpa.getUserHasRoleSecurityList())); 
      } 
     }else{ 
      System.out.println("The *idToken* object is null !!!"); 
     } 
    } catch (GeneralSecurityException | IOException e) { 
     e.printStackTrace(); 
    } 

    throw new MyCustomException("Google token is invalid or has expired"); 
} 

Zu meiner CLIENT_ID erstelle ich Anweisungen befolgt hier:

https://developers.google.com/identity/sign-in/web/devconsole-project

Das Problem ist, dass verifier.verify Rückkehr hält null.

Ich habe überprüft:

  • mein Benutzer mit Google registriert haben und die Datenbankfelder richtig

    gefüllt
  • i verschiedene String-Token von Google jedes Mal bekomme ich versuche google_sign_in

  • mein CLIENT_ID ist in der Google-Konsole gültig und aktiv.

Um die Verwirrung zu ergänzen, funktionierte dieses Ganze vor einem Monat gut. Ich bin krankgeschrieben und als ich zurück kam, begrüßte mich mein Chef mit diesem Problem.

Wer hat eine Idee, was passiert sein könnte?

Antwort

0

Ich habe es endlich herausgefunden.

Da niemand wusste, wie ich helfen kann, habe ich die Google-Bibliotheken fallengelassen und bin gegangen und habe meine eigene Token-Verifikation von Grund auf neu gemacht.

Ich ging hin und verwendet, um die Google-Token-Verifizierer-url-Tool hier:

https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123

Am unteren Rand der Seite hier

https://developers.google.com/identity/protocols/OpenIDConnect

, fand ich, wie man entziffern Sie den JSON.

Was ich tue, ist, ich kontaktiere ihr Online-Tool in Code, erhalten Sie die JSON-Antwort und verifizieren Sie es manuell. Dies ist mein Code:

private Map<String,String> getMapFromGoogleTokenString(final String idTokenString){ 
     BufferedReader in = null; 
     try { 
      // get information from token by contacting the google_token_verify_tool url : 
      in = new BufferedReader(new InputStreamReader(
             ((HttpURLConnection) (new URL("https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=" + idTokenString.trim())) 
             .openConnection()).getInputStream(), Charset.forName("UTF-8"))); 

      // read information into a string buffer : 
      StringBuffer b = new StringBuffer(); 
      String inputLine; 
      while ((inputLine = in.readLine()) != null){ 
       b.append(inputLine + "\n"); 
      } 

      // transforming json string into Map<String,String> : 
      ObjectMapper objectMapper = new ObjectMapper(); 
      return objectMapper.readValue(b.toString(), objectMapper.getTypeFactory().constructMapType(Map.class, String.class, String.class)); 

     // exception handling : 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch(Exception e){ 
      System.out.println("\n\n\tFailed to transform json to string\n"); 
      e.printStackTrace(); 
     } finally{ 
      if(in!=null){ 
       try { 
        in.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
     return null; 
    } 

    // chack the "email_verified" and "email" values in token payload 
    private boolean verifyEmail(final Map<String,String> tokenPayload){ 
     if(tokenPayload.get("email_verified")!=null && tokenPayload.get("email")!=null){ 
      try{ 
       return Boolean.valueOf(tokenPayload.get("email_verified")) && tokenPayload.get("email").contains("@gmail."); 
      }catch(Exception e){ 
       System.out.println("\n\n\tCheck emailVerified failed - cannot parse "+tokenPayload.get("email_verified")+" to boolean\n"); 
      } 
     }else{ 
      System.out.println("\n\n\tCheck emailVerified failed - required information missing in the token"); 
     } 
     return false; 
    } 

    // check token expiration is after now : 
    private boolean checkExpirationTime(final Map<String,String> tokenPayload){ 
     try{ 
      if(tokenPayload.get("exp")!=null){ 
       // the "exp" value is in seconds and Date().getTime is in mili seconds 
       return Long.parseLong(tokenPayload.get("exp")+"000") > new java.util.Date().getTime(); 
      }else{ 
       System.out.println("\n\n\tCheck expiration failed - required information missing in the token\n"); 
      } 
     }catch(Exception e){ 
      System.out.println("\n\n\tCheck expiration failed - cannot parse "+tokenPayload.get("exp")+" into long\n"); 
     } 
     return false; 
    } 

    // check that at least one CLIENT_ID matches with token values 
    private boolean checkAudience(final Map<String,String> tokenPayload){ 
     if(tokenPayload.get("aud")!=null && tokenPayload.get("azp")!=null){ 
      List<String> pom = Arrays.asList("MY_CLIENT_ID_1", 
              "MY_CLIENT_ID_2", 
              "MY_CLIENT_ID_3"); 

      if(pom.contains(tokenPayload.get("aud")) || pom.contains(tokenPayload.get("azp"))){ 
       return true; 
      }else{ 
       System.out.println("\n\n\tCheck audience failed - audiences differ\n"); 
       return false; 
      } 
     } 
     System.out.println("\n\n\tCheck audience failed - required information missing in the token\n"); 
     return false; 
    } 

    // verify google token payload : 
    private boolean doTokenVerification(final Map<String,String> tokenPayload){ 
     if(tokenPayload!=null){ 
      return verifyEmail(tokenPayload) // check that email address is verifies 
       && checkExpirationTime(tokenPayload) // check that token is not expired 
       && checkAudience(tokenPayload) // check audience 
       ; 
     } 
     return false; 
    } 

Sobald ich diese detaillierte Überprüfung gehabt haben, ich in der Lage war, genau zu sehen, wo der Fehler war; Das Frontend hat mir einen ungültigen CLIENT_ID-Wert gesendet. [murren, murren] Ich habe sie etwa hundert Mal darüber gefragt und sie sagten mir, dass diese Werte übereinstimmen. BAH!

Also der Fehler war nicht irgendwo in meinem ursprünglichen Code für Token Verifikation, es war ein Fehler in der Kommunikation in meinem Büro.

Ich werde dieses Mal aus Sicherheitsgründen auf den ursprünglichen Code mit der richtigen CLIENT_ID zurückgreifen. Trotzdem muss ich eine Beschwerde über die Google-Bibliothek einreichen - sie hat mir nie gesagt, warum die Token-Überprüfung fehlgeschlagen ist. Ich brauchte TAGE Schmerz, um sich die Mühe zu machen, es endlich herauszufinden. Ich weiß, dass sie es aus Sicherheitsgründen gemacht haben, aber trotzdem ist der Mangel an Unterstützung unerträglich.