Fork me on GitHub
#cljsrn
<
2023-03-02
>
Loic06:03:44

Hi, quick question regarding ring session cookies in react native. For the web, having a simple ring middleware (https://github.com/skydread1/flybot.sg/blob/master/server/src/flybot/server/core/handler/middleware.clj#L31) allows me to save the session in a cookie that will automatically be send with all requests (I am using re-frame-http-fx for that). However, in React native, I thought it would work the same but my cookie is not received after my oauth2 login when I return to my app landing screen. I want to have the same logic for both web and mobile because most of the oauth2 is server-side anyway, that is why I only changed the landing url to my-app:// How can I get the session-id after landing back to my app? And do I need to handle the cookie storage myself? Thank you

joshmiller17:03:21

RN isn’t a browser context so doesn’t have built-in cookie management. If you’re using OAuth2, I think the simplest thing to do is to extract the access token you get in the response and then inject that into each request you make.

Loic01:03:54

I see. But when I perform the redirect to my app, I don't see how I can fetch the cookie to store it in the first place. My oauth2 flow is like this: • request to http://localhost:9500/oauth/google/login • after login success with google, redirect to my server end point /oauth/google/success • in the handler of the success, I use the access-token to fetch user info, store in db and add user name and permission to ring session • I then redirect the request (with the session that would be put in a cookie by ring) to my home page of my website (this work) or to the home screen of my app via Linking my-app:// and this prompt me if I wanna go back to the app after google login and if click yes it goes back to the app. However, in the mobile app, I need to retrieve the cookie somehow to read user from it and store it somewhere as you mentioned. You said, RN does not store cookie for me, but how can I get the cookie from the response? I tried using @react-native-cookies/cookies but without success. To open the oauth/google/login, I used

#(.openURL Linking "")
I am bit new to RN and maybe there is a step I am missing or I just cannot do it this way?

joshmiller01:03:48

I think what you’re looking for is the URL string in the redirect back to my-app:// — you should be getting something like

Loic02:03:29

This is what my session looks like on the server with what google returns:

{:oauth2/access-tokens
 {:google
  {:token "access-token"
   :extra-data {:scope " openid ",
                :token_type "Bearer"}
   :expires #object[org.joda.time.DateTime 0x4d5fe305 "2023-03-03T02:53:11.146Z"]
   :id-token "id-token"}}
 :user-id "user-id" ;; my own addition
 :user-roles (:editor :admin) ;; my own addition
}
So I think I need to pass • :toker-id because it is the one containing the user data • :user-id and :user-roles because I need it as well What is the secret-token you are mentioning?

joshmiller04:03:40

secret_token was just made up, I haven’t worked with the Google OAuth implementation in a while so I don’t remember exactly what the params are. The token and id-token are injected into your session by your web server, which is interpreting the params in the redirect request it gets (e.g., ). So in your app, you need to capture that string when it’s used to open your app after Google redirects you back.

Loic08:03:00

Thank you very much for the clarification. I tried to add an eventListener on the Linking in the frontend react native like so

(.addEventListener Linking "url" (fn [url] (println url)))
and in my redirect string url in my server like this
(str "my-app://?id-token=" (-> session :oauth2/access-tokens :google :id-token))
It logs me in Google, return to the app but the Listener is just ignored. I saw some example where people use it in the useEffect but in cljs/re-frame, we do not have such thing so I am not sure how I can capture this string.

joshmiller17:03:47

Hm, that event listener fn you have looks fine to me, and should print your url to the console. Can you double-check that the event listener is being added (maybe add like (println "adding event listener") just above)? It’s possible it’s being added in the wrong place, or you need to restart the app, or something similar.

Loic03:03:14

Ok, I can finally capture the string. The code was not the problem, I needed to add some config in :

#import <React/RCTLinkingManager.h>

/// listen to incoming app links during your app's execution
- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

🙌 2
Loic01:03:04

@U0E1JV8GK, I ended up writing a https://github.com/skydread1/flybot.sg/blob/master/server/src/flybot/server/core/handler/middleware.clj#L33 to get the ring-session cookie created by ring and passing it to the url in case the redirect Location is my-app:// and then I am able to capture this ring-session via the Linking Listener. To store the cookie on mobile I used https://react-native-async-storage.github.io/async-storage/docs/install/. It returns Promises, so I had to add additional re-frame dispatch in the Promise.then() to be sure my cookie is pulled before the app is initialised (http request to get post, user etc). Passing the cookie in the request was quite straight forward, I just added :headers {:cookie my-cookie} to the :http-xhrio fx for all the requests that require a session. I just wanted to explain what worked for me for future reference in case someone is facing the same issue. I am wondering if it is safe to just store the ring-session in AsyncStorage just like that? On my clients (web or mobile), I don't even read the value of the cookie I just pass it to every request and all the verification is done server side. Even my oauth2 redirect is actually not going to the client directly with the code but back to my server that would put tokens + some user info in the session for ring to encrypt in ring-session. I hope it is a correct way to do it. Thank you again for the help

joshmiller15:03:59

AsyncStorage should be fine, it’s sandboxed to your app, so not available to anyone else.

joshmiller15:03:04

Glad you got to a good solution!