Once (?) in awhile, we developers browse the web for some quick and dirty solutions to some of our coding problems (sometimes not even problems, right?). This is another of those days, everything was going fine on this project I am currently working on. This is not a social networking sites but a site for sharing and comunicating (how I missed the days of the chatrooms) similar in many aspect to Digg and DZone but which also allows users to communicate in realtime and leave comments. So the back-end was sort of completed but so now time to focus on the user registration.
The sites needed to be open and avoid repeatitive tasks such registering users. The way forward was to implement some authentication to allow users to register with some sort of universally accessible ID (or sort of). Facebook Connect, OpenSocial and Google Accounts have their advantages but to me personally; the disadvantages outweight the pros. These are some of the disadvantages of those platform:
Enter OpenID. OpenID has been around longer than most Internet-based decentralised authentication platform. The beauty of this platform is that it also supported by most (if not all) large site on the Internet. From AOL, BBC, CNN to YAHOO and ZIMBRA, as I said most sites (based on the alphabet) support OpenID, check the OpenID Directory. It was recently announced that OpenID has reached 1Billion enabled accounts (read here). Based on those figures, I decided that OpenID for now was the authentication choice for this application. I will not be discussing any security issues in this entry, there are plenty of resources available on the Internet for that.
OK, so I am a Java developer and I am developing the front-end using GWT and Java on the server-side. I searched on the Internet for solutions on how to implement the authentication as GWT RPC are different to normal servlet call. I spent more time reading about the OpenID specification and implementations examples on the Internet. I have to admit that some of tutorials that I found on the Internet were somehow confusing and not helpful at all. Therefore I decided to write my own Dummies Guide to GWT and OpenID.
Dummies Guide to GWT and OpenID
First of all, it is important to know how OpenID works (please check the OpenID site for more info).
In a nutshell, OpenID allows you to authenticate with website (supporting the standard) with just an URL and voila. Your URL has to be hosted by an OpenID provider in order for it to work. For example, my blog is hosted by Google on blogspot.com. Google supports OpenID authentication therefore if a reader wanted to leave a comment on my blog, he does not have to have a Google Account as he can log-in with his Yahoo or AOL or Facebook or Wordpress or any other OpenID provider sites, and then leave a comment, that simple.
GWT to OpenID and back
There are two ways to authenticate a user with an OpenID provider and GWT supports both. When authenticating a user, the relaying site (the site the user is trying to access) redirects to user to the OpenID provider (i.e. Google) login page.
The problem will be with the GWT RPC mechanism. GWT RPC calls are asynchronous and you cannot make any redirections. Therefore we need a way to execute the redirection from the client side, here is the code (I use OpenID for Java to handle the openID discovery from the RPC servlet), I then used USER object (just a simple POJO which only stores the redirection URL and the parameters) to be sent back and forth between the front-end and back-end.
#######################################################
#############################################################
The above codes will format the request in order for the front-end to execute a redirect and allow the user to authenticate with his OpenID provider. Now here is the front-end code which executes the authentication and reads the data back.
#################################################################
I have attached the full NetBeans project with dependencies. The code is provided as-is and use at your own risk ;). Here is a screenshot of the working application:
Step1: Authenticate on the site (enter the URL)
Step2: Redirect to OpenID provider (Google is my provider :) ), authenticate with your provider
Step3: Allow the application to access your OpenID details and redirect back to the original site
Step4: final step, check the parameters from the provider and proceeds accordingly
Take a look at the URL in each of the above step to see the OpenID data. OK, so my code actually works (yuppie), now you know that it is possible form GWT to OpenID and it's not as complicated as many other sites are trying to show. The code is just for authentication but once authenticated, you can retrieve any parameters that you need. In this example, the query is sent through the browser URL (GET) but you can change it to be encoded in a form submit action. Iwrote some of the code to allow the user to authenticate via a popup window, the code is not complete and maybe someone else might want to have a go. My only problem is getting the redirect back to the original window but apart from that it works.
Download the source code
I hope you guys enjoyed it and Happy Coding.
The sites needed to be open and avoid repeatitive tasks such registering users. The way forward was to implement some authentication to allow users to register with some sort of universally accessible ID (or sort of). Facebook Connect, OpenSocial and Google Accounts have their advantages but to me personally; the disadvantages outweight the pros. These are some of the disadvantages of those platform:
- Facebook is a popular site hence is its platform, Facebook Connect, in mostly Europe and America but not everybody in Europe and America have a Facebook account.
- OpenSocial, when it comes to single logon, has more advantages than Facebook. I supposed that if we do take into consideration all the OpenSocial sites, we might have apossible larger user based than supporting Facebook alone. Even that was too limited.
- Google Accounts, one thing Google does not advertise its user base. I could be wrong but do anybody actually knows how many people uses the various Google services (excluding search). Google has the same disadvantages as Facebook.
Enter OpenID. OpenID has been around longer than most Internet-based decentralised authentication platform. The beauty of this platform is that it also supported by most (if not all) large site on the Internet. From AOL, BBC, CNN to YAHOO and ZIMBRA, as I said most sites (based on the alphabet) support OpenID, check the OpenID Directory. It was recently announced that OpenID has reached 1Billion enabled accounts (read here). Based on those figures, I decided that OpenID for now was the authentication choice for this application. I will not be discussing any security issues in this entry, there are plenty of resources available on the Internet for that.
OK, so I am a Java developer and I am developing the front-end using GWT and Java on the server-side. I searched on the Internet for solutions on how to implement the authentication as GWT RPC are different to normal servlet call. I spent more time reading about the OpenID specification and implementations examples on the Internet. I have to admit that some of tutorials that I found on the Internet were somehow confusing and not helpful at all. Therefore I decided to write my own Dummies Guide to GWT and OpenID.
Dummies Guide to GWT and OpenID
First of all, it is important to know how OpenID works (please check the OpenID site for more info).
In a nutshell, OpenID allows you to authenticate with website (supporting the standard) with just an URL and voila. Your URL has to be hosted by an OpenID provider in order for it to work. For example, my blog is hosted by Google on blogspot.com. Google supports OpenID authentication therefore if a reader wanted to leave a comment on my blog, he does not have to have a Google Account as he can log-in with his Yahoo or AOL or Facebook or Wordpress or any other OpenID provider sites, and then leave a comment, that simple.
GWT to OpenID and back
There are two ways to authenticate a user with an OpenID provider and GWT supports both. When authenticating a user, the relaying site (the site the user is trying to access) redirects to user to the OpenID provider (i.e. Google) login page.
The problem will be with the GWT RPC mechanism. GWT RPC calls are asynchronous and you cannot make any redirections. Therefore we need a way to execute the redirection from the client side, here is the code (I use OpenID for Java to handle the openID discovery from the RPC servlet), I then used USER object (just a simple POJO which only stores the redirection URL and the parameters) to be sent back and forth between the front-end and back-end.
#######################################################
public User authenticateOpenId(String provider_url) {
try {
ConsumerManager manager = new ConsumerManager();
// This is the URL where the OpenID provider will redirect the user
// once logged in.
String returnToUrl = "http://localhost:8084/GwtOpenId";
// the provider URL will be used to identify the user OpenID provider
List discoveries = manager.discover(provider_url);
DiscoveryInformation discovered = manager.associate(discoveries);
// OpenID 4 Java needs to have an HttpServletRequest object, GWT sevlet
have
// convenient methods to retrieve the HttpServletRequest object
and manipulate its
// parameters
this.getThreadLocalRequest().setAttribute("openid-disc", discovered);
this.getThreadLocalRequest().setAttribute("openid.mode", "popup");
AuthRequest authReq = manager.authenticate(discovered, returnToUrl);
FetchRequest fetch = FetchRequest.createFetchRequest();
// I want to exchange the following attributes from the OpenID provider
// remember that teh attribute will be returned only if it exits
fetch.addAttribute("email","http://schema.openid.net/contact/email",true);
authReq.addExtension(fetch);
// Simple POJO to persist the data
User user = new User();
// In a normal servlet development, the following statement would make
// a redirect call but this would not work when using GWT RPC
if(!discovered.isVersion2()){
user.setRedirect(authReq.getDestinationUrl(true));
// fakes the redirect by sending the POJO with the required parameters
// to make a client-side redirect
return user;
} else{
user.setParams(authReq.getParameterMap());
user.setRedirect(authReq.getDestinationUrl(false));
// fakes the redirect by sending the POJO with the required parameters
// to make a client-side redirect
return user;
}
} catch (MessageException ex) {
Logger.getLogger(GWTServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (DiscoveryException ex) {
Logger.getLogger(GWTServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (ConsumerException ex) {
Logger.getLogger(GWTServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
#############################################################
The above codes will format the request in order for the front-end to execute a redirect and allow the user to authenticate with his OpenID provider. Now here is the front-end code which executes the authentication and reads the data back.
#################################################################
// This is an extract from the openidEntryPoint.java
// This is where the magic happens - This code is only usefull when the OpenID
provider
// redirects the user back to your site - please visit openid.net for valid
parameters.
// The "if" statement checks to make sure that it is a valid response from
the OpenID
// provider - You can do anything you want with the results here such
as verifying the
// response with the server-side code
if(Window.Location.getParameter("openid.rpnonce") != null){
String s = Window.Location.getParameter("openid.mode");
// executes this if the user cancels the authentication process and the OpenID
// providers returns to the your site
if(s.equals("cancel")){
sign.setText("Server returned openid.mode=cancel");
openIdUrl.setText("You need to Accept not Cancel");
}
// Here, I am assuming that everything is fine and that the user has
been sucessfully logged in
else{
sign.setText("You have successfully signed in");
vp.setVisible(false);
}
}
RootPanel.get().add(contentPanel);
}
private class UserAsyncCallback implements AsyncCallback<User> {
public void onFailure(Throwable caught) {
Window.alert(caught.getLocalizedMessage());
}
public void onSuccess(User result) {
if (result != null) {
// Window.open(result.getRedirect(), "_blank",
"height=200,width=400,left=100," +
// "top=100,resizable=no,scrollbars=no,
toolbar=no,status=yes");
// this the most important line in order to make the authentication.
Here, I am redirecting the user
// from the client side to the OpenID provider URL with the discovery
data generated from the
// RPC call to the servlet.
Window.Location.assign(result.getRedirect());
} else {
Window.alert("Ooops!!! Couldn't find your provider");
}
}
}
#######################################################################################################
I have attached the full NetBeans project with dependencies. The code is provided as-is and use at your own risk ;). Here is a screenshot of the working application:
Step1: Authenticate on the site (enter the URL)
Step2: Redirect to OpenID provider (Google is my provider :) ), authenticate with your provider
Step3: Allow the application to access your OpenID details and redirect back to the original site
Step4: final step, check the parameters from the provider and proceeds accordingly
Take a look at the URL in each of the above step to see the OpenID data. OK, so my code actually works (yuppie), now you know that it is possible form GWT to OpenID and it's not as complicated as many other sites are trying to show. The code is just for authentication but once authenticated, you can retrieve any parameters that you need. In this example, the query is sent through the browser URL (GET) but you can change it to be encoded in a form submit action. Iwrote some of the code to allow the user to authenticate via a popup window, the code is not complete and maybe someone else might want to have a go. My only problem is getting the redirect back to the original window but apart from that it works.
Download the source code
I hope you guys enjoyed it and Happy Coding.
Hi Armel
ReplyDeleteThis is a very good start - but I think the example is incomplete (or it may be that I don't understand what you have done).
The problem is the parameters coming back from the OpenID provider need to be verified. Otherwise anyone could just perform a GET with the right parameters and be "authenticated" without actually going through the openid provider.
The verification needs to be done via a call to the openid4java library. So you either need to compile this client side (a tricky proposition -I don't think the GWT compiler would convert all of the openid4java library to javascript) - or you have to perform the work on the server side.
I think you could extend the example to have the client call back to another server side function that does the verification. The same consumer manager used to create the request has to verify it.
I am working on getting this going - so I will ping you if I get it working.
@wstrange the code that I wrote was actually adapted from the openid4java example (http://code.google.com/p/openid4java/wiki/SampleConsumer) and if you take a look at the second method, it that part that verifies the authentication. This is not the hardest part so I believe to covered the most important aspect. You can make the ConsumerManager to be a singleton as that it will be the same object that has generated the initial provider and then verifies it. You can also store it the object if you do not want it as a singleton so that you cache the object for later retrieval. Let me know if you need more clarification on the subject.
ReplyDeleteThanks for the comment.
Hi Armel
ReplyDeleteThe openid4java SampleConsumer example uses a session variable to store the discovery information used to generate the request. This discovery state is unique for each web client and must be used to validate the response.
In your example above you are using thread local storage (not a session variable) and you don't appear to be calling the manager.verify() method to verify that the response from the OP is valid. The parameters passed back in the redirect must be verified (you can't just extract them from the URL and assume they are valid - this can be spoofed). I can't see where your code is doing the verification.
I don't believe making the consumer manger a singleton is doing what you think it is. It's the discovery information that is generated by the manager that needs to be stored per client instance:
DiscoveryInformation discovered = manager.associate(discoveries);
and then retrieved from the session (or other mechanism) to perform validation on the parameters coming back from the OP:
DiscoveryInformation discovered = (DiscoveryInformation)
httpReq.getSession().getAttribute("openid-disc");
VerificationResult verification = manager.verify(
receivingURL.toString(),
response, discovered);
I think your example "works" in the sense that it lets someone logon. But if you are blinding trusting the URL parameters this is not secure.
Warren
Hi Warren,
ReplyDeleteYou are right as stated in the blog article, I was just demonstrating how to implement a OpenID using GWT as they were interest about it in forums. As soon as I have sometimes to focus on this article, I will extend it to implement the verification. Off-my head, I supposed you can save the instance in some sort of caching and use a unique identifier key to retrieve the value when you need it. You should also think about putting an expiry on the cache for security reasons.
Also, if anybody has already implemented the verification process using GWT as above, please do share it.
Armel
Hi Armel, I have written a post about my implementation of your code into grails / GWT and adding server-side verification of the OpenId response through service-side session storage.
ReplyDeleteTake a look at:
http://code-omen.blogspot.com/2010/10/dum-guide-to-openid-gwt-and-grails.html
Hi Armel,
ReplyDeleteI am using GWT/GAE with the jar - openid4java-gaehacks-0.9.5-593.jar
I get the following:
With https://me.yahoo.com, the response is
Sorry! You will not be able to link your Yahoo! account with this website or application. It is using an older version of the OpenID technology.
With https://www.google.com/accounts/o8/id, the response is
The page you requested is invalid.
Any help ?
Try changing:
Deleteuser.setRedirect(authReq.getDestinationUrl(false));
to
user.setRedirect(authReq.getDestinationUrl(TRUE));
in authenticateOpenId(String provider_url) method when discovered is version2.
I've been struggling for like 2 weeks to make this work with openid4java-gaehacks-0.9.5 thinking it was because the version of the library. Tried to mix up some things of the newest version (0.96), built with ant and still didn't work. I was almost going to give up.
DeleteSuddenly, today, when I was about to surrender, I get to see your bless reply. I have no words to describe my thankfulness to you. Just thank you SO MUCH.
I too want to add OpenId login support to my GWT app. This was originally posted Dec 2009, based on the comments it seems the code was almost working? Did you ever get it finished? Is the redirect back to original window working? If you have some updated code could you update the post or send to me dhoffer6 at gmail dot com, many thanks!
ReplyDeleteI am so happy after read your blog. It’s very useful blog for us.
ReplyDeleteJava Corporate training for employees in Nigeria
Thanks for sharing this valuable information and we collected some information from this blog.
ReplyDeleteIn house Management training
Thanks for sharing such a wonderful post.
ReplyDeleteสมัครแทงบอล สมัครแทงบอล สมัครแทงบอล สมัครแทงบอล
This Is Really Useful And Nice Information.
ReplyDeleteสมัครแทงบอล สมัครแทงบอล สมัครแทงบอล
Hello everyone, Are you into trading or just wish to give it a try, please becareful on the platform you choose to invest on and the manager you choose to manage your account because that’s where failure starts from be wise. After reading so much comment i had to give trading tips a try, I have to come to the conclusion that binary options pays massively but the masses has refused to show us the right way to earn That’s why I have to give trading tips the accolades because they have been so helpful to traders . For a free masterclass strategy kindly contact (paytondyian699@gmail.com) for a free masterclass strategy. He'll give you a free tutors on how you can earn and recover your losses in trading for free..
ReplyDeleteI was surfing net and fortunately came across this site and found very interesting stuff here. Its really fun to read. I enjoyed a lot. Thanks for sharing this wonderful information. buku mimpi 3d
ReplyDeletevery interesting
ReplyDeleteเว็บพนัน1XBET
สูตรบาคาร่า
We are really grateful for your blog post. You will find a lot of approaches after visiting your post. Great work iphonewiz
ReplyDeleteI conceive you have noted some very interesting points, regards for the post.
ReplyDeleteทางเข้าเว็บพนันW88
Wohh just what I was looking for, regards for posting.
ReplyDeleteรีวิวUFASLOT
I value the article.Thanks Again. Much obliged. เกมสล็อตออนไลน์ยูฟ่าเบท เว็บพนันสล็อตออนไลน์ เว็บเดิมพันยูฟ่าสล็อต
ReplyDeleteI will bookmark your site and take the feeds additionally คาสิโน AE Sexy . คาสิโนSexygaming . AE casino
ReplyDeleteI am thankful to you for sharing this plethora of useful information. I found this resource utmost beneficial for me. Thanks a lot for hard work.
ReplyDeleteคาสิโนออนไลน์UFABET
เว็บพนันออนไลน์ufacasino
คาสิโนออนไลน์ที่ดีที่สุด
I conceive you have noted some very interesting points, regards for the post. เล่นบาคาร่าออนไลน์ . บาคาร่าSA Gaming . บาคาร่าSA Gamingดีอย่างไร .
ReplyDeleteWohh just what I was looking for, regards for posting. เว็บแทงบอลออนไลน์UFABET . แทงบอลออนไลน์UFABET . สมัครสมาชิกUFABET .
ReplyDeleteI am thankful to you for sharing this plethora of useful information. I found this resource utmost beneficial for me. Thanks a lot for hard work.
ReplyDeleteSA Gaming
SA Gaming Casino
I read this article. I think You put a lot of effort to create this article. I appreciate your work. venus casino online . เดิมพันออนไลน์Venus Casino . แนะนำเว็บVenus Casino
ReplyDeleteI conceive you have noted some very interesting points, regards for the post... ทางเข้าVenus Casino . สมัครสมาชิกVenus Casino . วิธีเดิมพันVenus Casino
ReplyDeleteWohh just what I was looking for, regards for posting. เว็บแทงบอลออนไลน์ยูฟ่าเบท
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work. เล่นบาคาร่าขั้นต่ำ10บาท . ทางเข้าเว็บแทงบาคาร่าออนไลน์ . ลิงค์ทางเข้าเว็บแทงบาคาร่าบนมือถือ
ReplyDeleteWohh just what I was looking for, regards for posting. คาสิโนเว็บUFABET
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits. เล่นเสือมังกรบนมือถือ
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work. เสือมังกรออนไลน์
ReplyDeleteWohh just what I was looking for, regards for posting. แทงบอลสเต็ปUFABET
ReplyDeleteI am thankful to you for sharing this plethora of useful information. I found this resource utmost beneficial for me. Thanks a lot for hard work. Sexy Baccarat
ReplyDeleteHere at this site really the fastidious material collection so that everybody can enjoy a lot. 交友網
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also. เดิมพันออนไลน์Venus Casino
ReplyDeleteI conceive you have noted some very interesting points, regards for the post แทงบอลเว็บไหนดี . แทงบอลออนไลน์เว็บไหนดี . แทงบอลออนไลน์ยูฟ่าเบท
ReplyDeleteI value the article.Thanks Again. Much obliged. วิธีเดิมพันเว็บsagaming เล่นSA GAME
ReplyDeleteWe provide best services to all class of clients. คาสิโนออนไลน์
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteI curious more interest in some of them hope you will give more information on this topics in your next articles. Best Infinix S5 Pro Mobile Phone Price in GERMANY
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits. ยูฟ่าเบท . เว็บพนันufabet
ReplyDeleteWohh just what I was looking for, regards for posting. กำถั่วขั้นต่ำ10บาท กำถั่วpantip
ReplyDeleteI am thankful to you for sharing this plethora of useful information. I found this resource utmost beneficial for me. Thanks a lot for hard work. รีวิวเว็บพนันUFABET
ReplyDeleteWohh just what I was looking for, regards for posting.เล่นเกมกำถั่วออนไลน์.รีวิวเว็บเกมกำถั่ว
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also UFA GAME UFA CASINO
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work. ยูฟ่าเบทคาสิโนออนไลน์ คาสิโนยูฟ่าเบทออนไลน์บนมือถือ
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work.วิธีเล่นufaslot.สมัครสมาชิกยูฟ่าสล็อต
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work. UFA SLOT ยูฟ่าสล็อต
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work. ทางเข้าเว็บรูเล็ตออนไลน์ สมัครเล่นรูเล็ตออนไลน์
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits. เกมยิงปลา . เกมยิงปลาแตกง่าย
ReplyDeleteI value the article.Thanks Again. Much obliged. บาคาร่าเว็บไหนดี2021
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work. เดิมพันคาสิโนยูฟ่าเบท คาสิโนยูฟ่าเบท2021
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work. เกมยิงปลาออนไลน์บนมือถือ. เว็บเกมยิงปลาฝาก-ถอนออโต้.
ReplyDeleteI value the article.Thanks Again. Much obliged.เล่นยูฟ่าเบท
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also ยูฟ่าเบทขั้นต่ำ10บาท
ReplyDeleteWe provide best services to all class of clients. แทงบอลขั้นต่ำ10บาท
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeletetop10 เว็บแทงบอลที่ดีที่สุด
แทงบอลufabetเว็บไหนดี?
I value the article.Thanks Again. Much obliged. Sexy gaming
ReplyDeleteI value the article.Thanks Again. Much obliged.
ReplyDeleteทางเข้าคาสิโนออนไลน์
Wohh just what I was looking for, regards for posting. คาสิโนออนไลน์บนมือถือ
ReplyDeleteI value the article.Thanks Again. Much obliged. คาสิโน AE Sexy . . sexybaccarat365s.com .
ReplyDeleteI value the article.Thanks Again. Much obliged. เว็บคาสิโนออนไลน์ .sexybaccarat365s.com
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeleteวิธีเล่นคาสิโนออนไลน์
I read this article. I think You put a lot of effort to create this article. I appreciate your work.
ReplyDeleteเดิมพันคาสิโนSexy.
sexybaccarat365s.com.
I will bookmark your site and take the feeds additionally.แนะนำเว็บยูฟ่าเบท
ReplyDeleteI conceive you have noted some very interesting points, regards for the post. ยูฟ่าเบท.
ReplyDeleteI conceive you have noted some very interesting points, regards for the post.
ReplyDeleteเล่นKingmakerบนมือถือ
Wohh just what I was looking for, regards for posting.
ReplyDeleteไฮโลKingmaker
We provide best services to all class of clients. สล็อตKingmaker
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits. แนะนำเว็บบอลUfabet.
ReplyDeleteI will bookmark your site and take the feeds additionally
ReplyDeleteแทงบอลได้เงินจริง
This is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also คาสิโนออนไลน์ยูฟ่าเบท
ReplyDeleteI conceive you have noted some very interesting points, regards for the post.
ReplyDeleteทางเข้าเดิมพันกีฬายูฟ่าเบท
I conceive you have noted some very interesting points, regards for the post. SlotUfabet
ReplyDeleteWe provide best services to all class of clients. สล็อตออนไลน์
ReplyDeleteI am thankful to you for sharing this plethora of useful information. I found this resource utmost beneficial for me. Thanks a lot for hard work. เล่นสล็อตบนมือถือ
ReplyDeleteI value the article.Thanks Again. Much obliged. สล็อตออนไลน์ฝากไม่มีขั้นต่ำ
ReplyDeleteWe provide best services to all class of clients. พนันกีฬาออนไลน์ยูฟ่าเบท
ReplyDeleteI conceive you have noted some very interesting points, regards for the post. ยูฟ่าเบทคาสิโนออนไลน์
ReplyDeleteI value the article.Thanks Again. Much obliged. สล็อตออนไลน์เว็บไหนดี.
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits. คาสิโนออนไลน์.
ReplyDeleteI will bookmark your site and take the feeds additionally Casino UFABET
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits. คาสิโนขั้นต่ำ10บาท.
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work.คาสิโนUfabet
ReplyDeleteI value the article.Thanks Again. Much obliged. Sexy Baccarat
ReplyDeleteWohh just what I was looking for, regards for posting.Sexy Baccarat
ReplyDeleteWe provide best services to all class of clients. เว็บคาสิโนออนไลน์.
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits.สมัครเล่นยูฟ่าเบท
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also. บาคาร่าออนไลน์
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also. ทางเข้าUFABET.
ReplyDeleteI conceive you have noted some very interesting points, regards for the post. รูเล็ตออนไลน์
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also. หวยยูฟ่าเบท .
ReplyDeleteI value the article.Thanks Again. Much obliged. ทางเข้าเว็บแทงบอลUFABET
ReplyDeleteWohh just what I was looking for, regards for posting. แทงบาคาร่า
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work. เล่นคาสิโนสดบาคาร่า.
ReplyDeleteI will bookmark your site and take the feeds additionally.สมัครสมาชิกเว็บแทงไฮโล
ReplyDeleteI conceive you have noted some very interesting points, regards for the post.พีจีสล็อต
ReplyDeleteWe provide best services to all class of clients. PGSLOT GAME
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeleteSicbo online
I conceive you have noted some very interesting points, regards for the post. Slot PG .
ReplyDeleteI value the article.Thanks Again. Much obliged. เล่นPGslot ขั้นต่ำ 10 บาท
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits. พีจีสล็อต.
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits. เว็บแทงบอลบนมือถือ . แทงบอลออนไลน์ยูฟ่าเบท . เดิมพันแทงบอลOnline
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeleteรีวิวเว็บรูเล็ตยูฟ่าเบท
I went to this website, and I believe that you have a plenty of excellent information, I have saved your site to my bookmarks. แทงไฮโลออนไลน์
ReplyDeleteI will bookmark your site and take the feeds additionally.UFABET
ReplyDeleteWohh just what I was looking for, regards for posting. Red Tigerบนมือถือ
ReplyDeleteWohh just what I was looking for, regards for posting.casino Red Tiger
ReplyDeleteI conceive you have noted some very interesting points, regards for the post.เล่นเสือมังกรออนไลน์
ReplyDeleteI conceive you have noted some very interesting points, regards for the post . Joker Gaming
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeleteเล่นเสือมังกรบนมือถือ
We provide best services to all class of clients.
ReplyDeleteรีวิวคาสิโนออนไลน์
เว็บรวมคาสิโน
แนะนำเว็บคาสิโนออนไลน์
I read this article. I think You put a lot of effort to create this article. I appreciate your work.
ReplyDeleteSpade gaming Slot Online
I value the article.Thanks Again. Much obliged. แทงหวยออนไลน์
ReplyDeleteI value the article.Thanks Again. Much obliged. เว็บหวยออนไลน์ที่ดีที่สุด.
ReplyDeleteWe provide best services to all class of clients. แทงบอลเต็งUFABET
ReplyDeleteWohh just what I was looking for, regards for posting. แทงไฮโลบนมือถือ
ReplyDeleteWe provide best services to all class of clients.
ReplyDeleteสมัครUFABET
Wohh just what I was looking for, regards for posting. ทางเข้าบาคาร่าUFABET . สมัครสมาชิกบาคาร่า . เดิมพันบาคาร่า
ReplyDeleteWohh just what I was looking for, regards for posting.เดิมพันสล็อตออนไลน์
ReplyDeleteI will bookmark your site and take the feeds additionally. UFAslot (ยูฟ่าสล็อต).
ReplyDeleteI value the article.Thanks Again. Much obliged. เล่นสล็อตออนไลน์
ReplyDeleteWe provide best services to all class of clients.
ReplyDeleteแทงบอลไทยufa365ดีมั้ย?
แทงบอลไทยพรีเมียร์ลีก
เดิมพันบอลไทย
I conceive you have noted some very interesting points, regards for the post. เว็บคาสิโนออนไลน์. รีวิวเว็บพนันออนไลน์. เว็บพนันบอลที่ดีที่สุด 2021.
ReplyDeleteI conceive you have noted some very interesting points, regards for the post. UFAslot (ยูฟ่าสล็อต)
ReplyDeleteI value the article.Thanks Again. Much obliged. เดิมพันไฮโลออนไลน์
ReplyDeleteWohh just what I was looking for, regards for posting. สมัครแทงบอลUFABET
ReplyDeleteI am thankful to you for sharing this plethora of useful information. I found this resource utmost beneficial for me. Thanks a lot for hard work. ไฮโลออนไลน์บนมือถือ.
ReplyDeleteI value the article.Thanks Again. Much obliged.
ReplyDeleteเสือมังกรออนไลน์
เดิมพันเสือมังกร
เกมไพ่เสือมังกร
I conceive you have noted some very interesting points, regards for the post. ทางเข้าแทงไฮโลออนไลน์
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work.เดิมพันไฮโลออนไลน์
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also. เล่นยูฟ่าเบทฝากไม่มีขั้นต่ำ . คาสิโนออนไลน์บนมือถือ . UFABETขั้นต่ำ10บาท
ReplyDeleteI will bookmark your site and take the feeds additionally.Roulette online
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeleteไพ่เสือมังกร
Wohh just what I was looking for, regards for posting.
ReplyDeleteแทงบอลฝากถอนไม่มีขั้นต่ำ
I conceive you have noted some very interesting points, regards for the post. สมัครสมาชิกufabet
ReplyDeleteI conceive you have noted some very interesting points, regards for the post.
ReplyDeleteเคล็ดลับสล็อตออนไลน์
We help them as much as we can. If they need assistance with research, writing, grammar, formatting or proofreading, we provide our assistance to help them build their career. แทงบอล . แทงบอลออนไลน์ยูฟ่าเบท . แทงบอลออนไลน์บนมือถือ
ReplyDeleteI conceive you have noted some very interesting points, regards for the post. เว็บเล่นบาคาร่าอันดับ 1
ReplyDeleteI conceive you have noted some very interesting points, regards for the post.
ReplyDeleteเว็บแทงบอลดีที่สุด.
เว็บพนันบอลที่ดีที่สุด 2022.
เว็บพนันออนไลน์.
Photos available on your site even though producing attention rapidly some quantity submits.ไฮโลออนไลน์
ReplyDeleteWohh just what I was looking for, regards for posting. สมัครUFABET.
ReplyDeleteWe provide best services to all class of clients.เกมพนันยูฟ่าเบท
ReplyDeleteAwesome and interesting article. Great things you’ve always shared with us. Thanks. Just continue composing this kind of post. สมัครเล่นป๊อกเด้งขั่นต่ำ 100 บาท
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also. สล็อตออนไลน์ขั้นต่ำ1บาท
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also.เว็บUFACASINO
ReplyDeleteWe provide best services to all class of clients
ReplyDeleteกติกาเล่นรูเล็ต
I conceive you have noted some very interesting points, regards for the post. แทงบอลออนไลน์ฝากไม่มีขั้นต่ำ . ทางเข้าแทงบอลUFABETบนมือถือ
ReplyDeleteWe provide best services to all class of clients. รีวิวUFASLOT
ReplyDeleteI value the article.Thanks Again. Much obliged.
ReplyDeleteคาสิโนออนไลน์
"***I wanted to thank you for this excellent read!! I definitely loved every little
ReplyDeletebit of it."
แทงบอลออนไลน์
แทงบอล
I will bookmark your site and take the feeds additionally.คาสิโนUFABETเว็บไหนดี.คาสิโนเว็บไหนดี.เว็บคาสิโนยูฟ่าเบทที่ดีที่สุด
ReplyDeleteI conceive you have noted some very interesting points, regards for the post.
ReplyDeleteบอลพรีเมียร์ลีก
Wow! This is the best information I have ever read and I hope to get new knowledge from this blog again. เกมสล็อตออนไลน์ที่ดีที่สุด
ReplyDeleteI will bookmark your site and take the feeds additionally.วิธีแทงบอลUFABET.แทงบอลออนไลน์UFABET.วิธีแทงบอลออนไลน์
ReplyDeleteWe provide best services to all class of clients.
ReplyDeleteslot online
I am so happy after read your blog. It’s very useful blog for us. tank you so mush. แทงบอล คาสิโน
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also. เว็บพนันออนไลน์UFABETดีมั้ย
ReplyDeleteWe provide best services to all class of clients.
ReplyDeleteรีวิวแทงบอลออนไลน์
Thanks for sharing such a wonderful post เว็บบอล
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeleteเว็บแทงบอลออนไลน์UFABET
แทงบอลออนไลน์
ReplyDeleteWohh just what I was looking for, regards for posting. เล่นบาคาร่าออนไลน์เว็บไหนดี . เล่นบาคาร่าUFABETเว็บไหนดี . บาคาร่าเว็บไหนดี2022 .
ReplyDeleteI have read your article couple of times because your views are on my own for the most part. It is great content for every reader. สมัครUFABETฝากขั้นต่ำ100 สมัครUFABETเว็บคาสิโนออนไลน์
ReplyDeleteI will bookmark your site and take the feeds additionally.คาสิโนUFABETเว็บไหนดี.คาสิโนเว็บไหนดี.คาสิโนยูฟ่าเบทที่มาแรงที่สุด
ReplyDeleteI went to this website, and I believe that you have a plenty of excellent information, I have saved your site to my bookmarks. เว็บคาสิโนUFABET
ReplyDeleteAny suggestion would be greatly appreciate.ทดลองเล่นสล็อตPG
ReplyDeleteI conceive you have noted some very interesting points, regards for the post. เว็บรวมคาสิโน
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeleteUFABET เดิมพัน24ชั่วโมง
Wohh just what I was looking for, regards for posting.
ReplyDeleteคาสิโนออนไลน์UFABET
Wohh just what I was looking for, regards for posting.
ReplyDeleteแทงบอลออนไลน์UFABET
This is very Amazing and Very Informative Artical we get alot of Informations from this artical
ReplyDeletewe really appreciate your team work keep it up and keep posting such a informative articles.
Thank you.
แทงบอลสด
We provide best services to all class of clients. แทงบอลสดUFABET . แทงบอลสดยูฟ่าเบท . สมัครสมาชิกแทงบอลสดออนไลน์
ReplyDelete
ReplyDeleteThank you for sharing this valuable information with us keep sharing.
ไฮโลออนไลน์
Wohh just what I was looking for, regards for posting. แนะนำคาสิโนยูฟ่าเบท
ReplyDeletePhotos available on your site even though producing attention rapidly some quantity submits.คาสิโน12Bet.คาสิโนออนไลน์แบรนด์12BET.เกมคาสิโนออนไลน์ยอดฮิต
ReplyDeleteI went to this website, and I believe that you have a plenty of excellent information, I have saved your site to my bookmarks. เล่นเกมไพ่ป๊อกเด้ง
ReplyDeleteWe provide best services to all class of clients. เล่นบาคาร่าบนมือถือ
ReplyDeleteWohh just what I was looking for, regards for posting.
ReplyDeleteเว็บเดิมพันสล็อตที่ดีที่สุด
Wohh just what I was looking for, regards for posting.
ReplyDeleteเว็บแทงบอลต่างประเทศยอดนิยม
It's content that is very helpful to me. thanks for the article...
ReplyDeleteเว็บเล่นรูเล็ตออนไลน์
I value the article.Thanks Again. Much obliged. เล่นเกมไพ่ป๊อกเด้ง
ReplyDeleteWohh just what I was looking for, regards for posting. รีวิวเว็บคาสิโนUFABET
ReplyDeleteWe provide best services to all class of clients.
ReplyDeleteเดิมพันพีจีสล็อตขั้นต่ำ1
The blog was very innovative. This will be stylish and creative.
ReplyDeleteวิธีทำเงินUFABET
Wohh just what I was looking for, regards for posting. สมัครแทงบอลออนไลน์เว็บตรง สมัครบอลเว็บตรงไม่ผ่านเอเย่นต์
ReplyDeleteThank you for the wonderful information. this article is really helpful. I have been searching for this article for long time.
ReplyDeleteเว็บแทงบอลออนไลน์ท่ดีที่สุด
Find a website about travel around the world.....
ReplyDeleteรูเล็ตออนไลน์สายฟ้า
This is awesome.
ReplyDeletepgslot365
This article is good, interesting and informative.
ReplyDeleteช่วงเวลาเล่นสล็อตpg
boneshia creates best leather designs.
ReplyDeletebest leather quality for 2021.
buy from boneshia.com to get the best services at affordable pricing.
แทงบอลออนไลน์ฟรีเว็บไหนดี
เว็บพนันบอลสมัครฟรี
เว็บพนันบอลออนไลน์ฟรีเครดิต
Wohh just what I was looking for, regards for posting. แทงบอลออนไลน์UFABET
ReplyDeleteWohh just what I was looking for, regards for posting. แทงบอลออนไลน์UFABET . รีวิวเว็บแทงบอลUFABET . แทงบอลออนไลน์เว็บไหนดี
ReplyDeleteSuggestions and ideas are greatly appreciated. แจกฟรีเครดิตคาสิโน
ReplyDeleteThis is a great web site, Good sparkling user interface and, very informative blogs. thanks. You may check our website also. ทางเข้าเล่นยูฟ่าสล็อตบนมือถือ
ReplyDeleteI read this article. I think You put a lot of effort to create this article. I appreciate your work.
ReplyDeleteทางเข้าเล่นเกมไพ่ป๊อกเด้ง
Wohh just what I was looking for, regards for posting.
ReplyDeleteเว็บแทงบอลสเต็ปออนไลน์
This is a very good story.
ReplyDeleteไพ่เสือมังกร
I conceive you have noted some very interesting points, regards for the post.เว็บevolutionเดิมพันขั้นต่ำ1บาท
ReplyDelete