1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use client::Client;
use error::Error;

#[derive(Debug, Deserialize)]
pub struct IdInfo {
    /// These six fields are included in all Google ID Tokens.
    pub iss: String,
    pub sub: String,
    pub azp: String,
    pub aud: String,
    pub iat: String,
    pub exp: String,

    /// This value indicates the user belongs to a Google Hosted Domain
    pub hd: Option<String>,

    /// These seven fields are only included when the user has granted the "profile" and
    /// "email" OAuth scopes to the application.
    pub email: Option<String>,
    pub email_verified: Option<String>,  // eg. "true" (but unusually as a string)
    pub name: Option<String>,
    pub picture: Option<String>,
    pub given_name: Option<String>,
    pub family_name: Option<String>,
    pub locale: Option<String>,
}

impl IdInfo {
    // Check the issuer, audiences, and (optionally) hosted domains of the IdInfo.
    //
    // Returns an error if the client has no configured audiences.
    pub fn verify(&self, client: &Client) -> Result<(), Error> {
        // Check the id was authorized by google
        match self.iss.as_str() {
            "accounts.google.com" | "https://accounts.google.com" => {}
            _ => { return Err(Error::InvalidIssuer); }
        }

        // Check the token belongs to the application(s)
        if client.audiences.len() > 0 && !client.audiences.contains(&self.aud) {
            return Err(Error::InvalidAudience);
        }

        // Check the token belongs to the hosted domain(s)
        if client.hosted_domains.len() > 0 {
            match self.hd {
                Some(ref domain) if client.hosted_domains.contains(domain) => {}
                _ => { return Err(Error::InvalidHostedDomain); }
            }
        }

        Ok(())
    }
}