Merge lp:~karni/ubuntu-sso-java-library/fix-oauth-time-drift into lp:ubuntu-sso-java-library

Proposed by Michał Karnicki
Status: Merged
Merged at revision: 17
Proposed branch: lp:~karni/ubuntu-sso-java-library/fix-oauth-time-drift
Merge into: lp:ubuntu-sso-java-library
Diff against target: 181 lines (+90/-8)
3 files modified
src/com/ubuntu/sso/UbuntuSingleSignOnAPI.java (+22/-0)
src/com/ubuntu/sso/authorizer/OAuthAuthorizer.java (+66/-7)
src/com/ubuntu/sso/util/ValidationUtil.java (+2/-1)
To merge this branch: bzr merge lp:~karni/ubuntu-sso-java-library/fix-oauth-time-drift
Reviewer Review Type Date Requested Status
Chad Miller (community) Needs Information
Review via email: mp+73034@code.launchpad.net

Description of the change

Fixed OAuth time drift issue by overriding getTimestamp method of OAuth consumer. Before use, OAuthAuthorizer.fixTimeDrift() should be called once for given server before the authorizer is used.

Fixed email validation regex utility, that did not accept some correct emails.

To post a comment you must log in.
17. By Michał Karnicki

Format the device time in logs.

Revision history for this message
Chad Miller (cmiller) wrote :

Do we really need email validation outside of actually trying it?

I'm pretty sure "[1539137169]!chad.miller" should be valid. The mail system implements mail standards better than we can. We should be able to dump a message into it, and let the transit itself be our validation.

Who owns that? Can we add @Deprecated on that boolean isValidEmail(String email) method?

review: Needs Information
Revision history for this message
Michał Karnicki (karni) wrote :

I didn't want to make an unnecessary request, if the e-mail isn't valid. If you think we shouldn't validate the email (alternatively, if you think the regex is wrong), I can turn it off.

About adding @Deprecated - it's used right after registration (which is currently turned off and launches the browser) and right after login (before the requests are made). Perhaps I shouldn't be checking the email, but sending an invalid email doesn't make sense to me either, does it?

Revision history for this message
Chad Miller (cmiller) wrote :

I don't think we should be peeking at the string to validate. The only validation that matters is whether it can traverse the mail transport system.

As an example of how hard it is to peek, for the class of email addresses that contain an "@", this is close to acceptable. (And there are more valid addresses than this format!)

^(?:(?:(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|\x5c(?=[@,"\[\]\x5c\x00-\x20\x7f-\xff]))(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|(?<=\x5c)[@,"\[\]\x5c\x00-\x20\x7f-\xff]|\x5c(?=[@,"\[\]\x5c\x00-\x20\x7f-\xff])|\.(?=[^\.])){1,62}(?:[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]|(?<=\x5c)[@,"\[\]\x5c\x00-\x20\x7f-\xff])|[^@,"\[\]\x5c\x00-\x20\x7f-\xff\.]{1,2})|"(?:[^"]|(?<=\x5c)"){1,62}")@(?:(?!.{64})(?:[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.?|[a-zA-Z0-9]\.?)+\.(?:xn--[a-zA-Z0-9]+|[a-zA-Z]{2,6})|\[(?:[0-1]?\d?\d|2[0-4]\d|25[0-5])(?:\.(?:[0-1]?\d?\d|2[0-4]\d|25[0-5])){3}\])$

Let me try to dig up the regex from the ORA book from the '90s, which consisted of most of a printed page of text.

Revision history for this message
Chad Miller (cmiller) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/com/ubuntu/sso/UbuntuSingleSignOnAPI.java'
2--- src/com/ubuntu/sso/UbuntuSingleSignOnAPI.java 2011-08-02 17:11:58 +0000
3+++ src/com/ubuntu/sso/UbuntuSingleSignOnAPI.java 2011-08-29 15:54:22 +0000
4@@ -28,6 +28,10 @@
5 import java.net.URISyntaxException;
6 import java.util.ArrayList;
7 import java.util.List;
8+import java.util.logging.Level;
9+import java.util.logging.Logger;
10+
11+import oauth.signpost.signature.HmacSha1MessageSigner;
12
13 import org.apache.http.HttpEntity;
14 import org.apache.http.HttpHeaders;
15@@ -73,6 +77,8 @@
16 import com.ubuntu.sso.util.HttpUtil.QueryStringBuilder;
17
18 public class UbuntuSingleSignOnAPI implements SingleSignOnAPI {
19+ private static final Logger LOGGER = Logger.getLogger("com.ubuntu.sso");
20+
21 private static final String DEFAULT_SERVICE_ROOT = "localhost:8000";
22 private static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded";
23 // API complains about trailing "; charset=UTF-8";
24@@ -109,6 +115,8 @@
25 */
26 public UbuntuSingleSignOnAPI(HttpClient httpClient, String scheme, String host,
27 Authorizer authorizer) {
28+ LOGGER.setLevel(Level.INFO);
29+
30 if (httpClient == null) {
31 final HttpParams httpParams = new BasicHttpParams();
32 // 30 second timeout. Sometimes pingU1() can take a while.
33@@ -123,6 +131,20 @@
34 this.authorizer = authorizer;
35 }
36
37+ public static void fixTimeDrift(HttpClient client) {
38+ try {
39+ if (client == null) {
40+ client = new DefaultHttpClient();
41+ }
42+ OAuthAuthorizer.fixTimeDrift(client,
43+ "http://login.ubuntu.com",
44+ "E, dd MMM yyyy HH:mm:ss z");
45+ } catch (Exception e) {
46+ LOGGER.severe(e.getMessage());
47+ e.printStackTrace();
48+ }
49+ }
50+
51 /* (non-Javadoc)
52 * @see com.ubuntu.sso.SingleSignOnAPI#setAuthorizer(com.ubuntu.sso.authorizer.Authorizer)
53 */
54
55=== modified file 'src/com/ubuntu/sso/authorizer/OAuthAuthorizer.java'
56--- src/com/ubuntu/sso/authorizer/OAuthAuthorizer.java 2011-07-18 22:09:38 +0000
57+++ src/com/ubuntu/sso/authorizer/OAuthAuthorizer.java 2011-08-29 15:54:22 +0000
58@@ -22,19 +22,34 @@
59
60 package com.ubuntu.sso.authorizer;
61
62+import java.io.IOException;
63+import java.text.DateFormat;
64+import java.text.ParseException;
65+import java.text.SimpleDateFormat;
66+import java.util.Date;
67 import java.util.StringTokenizer;
68+import java.util.logging.Logger;
69
70 import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
71 import oauth.signpost.http.HttpParameters;
72 import oauth.signpost.signature.OAuthMessageSigner;
73 import oauth.signpost.signature.PlainTextMessageSigner;
74
75+import org.apache.http.Header;
76+import org.apache.http.HttpResponse;
77+import org.apache.http.HttpStatus;
78+import org.apache.http.client.ClientProtocolException;
79+import org.apache.http.client.HttpClient;
80+import org.apache.http.client.methods.HttpHead;
81 import org.apache.http.client.methods.HttpUriRequest;
82
83 import com.ubuntu.sso.entry.AuthenticateResponse;
84
85-public class OAuthAuthorizer implements Authorizer {
86- private final CommonsHttpOAuthConsumer consumer;
87+public class OAuthAuthorizer extends CommonsHttpOAuthConsumer
88+ implements Authorizer {
89+ private static final long serialVersionUID = -5429816815093116827L;
90+
91+ private static long timeDriftMillis = 0L;
92
93 /**
94 * Creates new OAuth {@link Authorizer} with given
95@@ -53,12 +68,12 @@
96 */
97 public OAuthAuthorizer(String consumerKey, String consumerSecret,
98 String tokenKey, String tokenSecret, OAuthMessageSigner signer) {
99- consumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);
100- consumer.setMessageSigner(signer);
101- consumer.setTokenWithSecret(tokenKey, tokenSecret);
102+ super(consumerKey, consumerSecret);
103+ setMessageSigner(signer);
104+ setTokenWithSecret(tokenKey, tokenSecret);
105 final HttpParameters params = new HttpParameters();
106 params.put("realm", "");
107- consumer.setAdditionalParameters(params);
108+ setAdditionalParameters(params);
109 }
110
111 /**
112@@ -107,10 +122,54 @@
113 public void signRequest(HttpUriRequest request)
114 throws AuthorizerException {
115 try {
116- consumer.sign(request);
117+ sign(request);
118 } catch (Exception e) {
119 e.printStackTrace();
120 throw new AuthorizerException(e);
121 }
122 }
123+
124+ // SSO Date header format: "E, dd MMM yyyy HH:mm:ss z"
125+ public static void fixTimeDrift(HttpClient client, String uri, String format)
126+ throws ClientProtocolException, IOException {
127+ final HttpUriRequest head = new HttpHead(uri);
128+ final HttpResponse response = client.execute(head);
129+ final Logger logger = Logger.getLogger("com.ubuntu.sso");
130+
131+ if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
132+ final Header dateHeader = response.getFirstHeader("Date");
133+ assert dateHeader != null;
134+
135+ logger.info("Server time: " + dateHeader.getValue());
136+ try {
137+ final DateFormat formatter = new SimpleDateFormat(format);
138+ final Date serverDate = formatter.parse(dateHeader.getValue());
139+ final long server = serverDate.getTime();
140+ final long device = System.currentTimeMillis();
141+ timeDriftMillis = server - device;
142+ if (timeDriftMillis > 300*1000) { // 300 seconds
143+ logger.warning("Device time DRIFTED: "
144+ + formatter.format(new Date(device)));
145+ }
146+ } catch (ParseException e) {
147+ logger.severe("Couldn't parse server time!");
148+ e.printStackTrace();
149+ }
150+ } else {
151+ logger.warning("Could not check time drift: " + response.getStatusLine());
152+ }
153+ }
154+
155+ public long getTimeDriftMillis() {
156+ return timeDriftMillis;
157+ }
158+
159+ public void setTimeDriftMillis(long millis) {
160+ timeDriftMillis = millis;
161+ }
162+
163+ @Override
164+ protected String generateTimestamp() {
165+ return Long.toString((System.currentTimeMillis() + timeDriftMillis) / 1000L);
166+ }
167 }
168
169=== modified file 'src/com/ubuntu/sso/util/ValidationUtil.java'
170--- src/com/ubuntu/sso/util/ValidationUtil.java 2011-07-12 12:24:19 +0000
171+++ src/com/ubuntu/sso/util/ValidationUtil.java 2011-08-29 15:54:22 +0000
172@@ -34,7 +34,8 @@
173 private static Pattern containsDigitPattern;
174
175 static {
176- isEmailPattern = Pattern.compile("\\w+.*@\\w+\\.[a-z]+"); // simple check
177+ isEmailPattern = Pattern.compile(
178+ "^[\\w\\-]+(\\.[\\w\\-]+)*@([A-Za-z0-9-]+\\.)+[A-Za-z]{2,4}$");
179 containsUppercasePattern = Pattern.compile(".*[A-Z]+.*");
180 containsDigitPattern = Pattern.compile(".*[0-9]+.*");
181 }

Subscribers

People subscribed via source and target branches