Skip to content

PPM SSO#848

Merged
gaborcsardi merged 26 commits into
mainfrom
feature/ppm-sso
May 14, 2026
Merged

PPM SSO#848
gaborcsardi merged 26 commits into
mainfrom
feature/ppm-sso

Conversation

@gaborcsardi
Copy link
Copy Markdown
Member

@gaborcsardi gaborcsardi force-pushed the main branch 2 times, most recently from 98336c1 to 3be8440 Compare March 11, 2026 09:49
@jmwoliver
Copy link
Copy Markdown

I've been testing this and it works great! It prompts me for the browser the first time and then uses the cached token on subsequent requests. I also tested install.packages() failing against an authenticated repo. Here's the output from testing this:

% rm ~/.ppm/tokens.toml
% R
> Sys.setenv(PACKAGEMANAGER_ADDRESS = "https://solo.packagemanager.posit.co")
> options(repos = c(PPM  = "https://__token__@solo.packagemanager.posit.co/cran-auth/latest"))
> pak::pkg_install("shiny")
✔ Loading metadata database ... done

→ Will update 1 package.
→ The package (1.90 MB) is cached.
+ rlang 1.2.0 → 1.2.0 🔧
? Do you want to continue (Y/n)
ℹ No downloads are needed, 1 pkg (1.90 MB) is cached
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Got rlang 1.2.0 (aarch64-apple-darwin20) (1.62 MB)
✔ Installed rlang 1.2.0  (35ms)
✔ 1 pkg + 29 deps: kept 15, upd 1, dld 1 (1.62 MB) [11.9s]
> pak::pkg_install("tidyverse")

→ Will update 17 packages.
→ Will download 5 CRAN packages (3.72 MB), cached: 12 (19.31 MB).
+ data.table 1.18.2.1 → 1.18.4 🔧
+ dplyr      1.2.0    → 1.2.1  🔧
+ haven      2.5.5    → 2.5.5  🔧 ⬇ (1.13 MB)
+ lubridate  1.9.5    → 1.9.5  🔧
+ readr      2.2.0    → 2.2.0  🔧
+ readxl     1.4.5    → 1.4.5  🔧 ⬇ (1.09 MB)
+ rlang      1.2.0    → 1.2.0  🔧
+ S7         0.2.2    → 0.2.2  🔧
+ tidyr      1.3.2    → 1.3.2  🔧
+ tidyverse  2.0.0    → 2.0.0   ⬇ (428.84 kB)
+ timechange 0.4.0    → 0.4.0  🔧
+ tzdb       0.5.0    → 0.5.0  🔧
+ uuid       1.2-2    → 1.2-2  🔧 ⬇ (76.14 kB)
+ vctrs      0.7.2    → 0.7.3  🔧
+ vroom      1.7.0    → 1.7.1  🔧
+ xml2       1.5.2    → 1.5.2  🔧 ⬇ (994.78 kB)
+ yaml       2.3.12   → 2.3.12 🔧
? Do you want to continue (Y/n) y
ℹ Getting 5 pkgs (3.72 MB), 12 (19.31 MB) cached
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Got readr 2.2.0 (aarch64-apple-darwin20) (785.42 kB)
✔ Got dplyr 1.2.1 (aarch64-apple-darwin20) (1.52 MB)
✔ Got readxl 1.4.5 (aarch64-apple-darwin20) (400.20 kB)
✔ Got haven 2.5.5 (aarch64-apple-darwin20) (382.03 kB)
✔ Got uuid 1.2-2 (aarch64-apple-darwin20) (48.90 kB)
✔ Got timechange 0.4.0 (aarch64-apple-darwin20) (172.56 kB)
✔ Got lubridate 1.9.5 (aarch64-apple-darwin20) (991.33 kB)
✔ Got vroom 1.7.1 (aarch64-apple-darwin20) (923.27 kB)
✔ Got S7 0.2.2 (aarch64-apple-darwin20) (322.71 kB)
✔ Got xml2 1.5.2 (aarch64-apple-darwin20) (714.49 kB)
✔ Got tidyr 1.3.2 (aarch64-apple-darwin20) (1.16 MB)
✔ Got tzdb 0.5.0 (aarch64-apple-darwin20) (676.01 kB)
✔ Got rlang 1.2.0 (aarch64-apple-darwin20) (1.62 MB)
✔ Got vctrs 0.7.3 (aarch64-apple-darwin20) (1.84 MB)
✔ Got tidyverse 2.0.0 (aarch64-apple-darwin20) (427.37 kB)
✔ Got yaml 2.3.12 (aarch64-apple-darwin20) (111.84 kB)
✔ Got data.table 1.18.4 (aarch64-apple-darwin20) (2.93 MB)
✔ Downloaded 17 packages (15.03 MB) in 3.8s
✔ Installed data.table 1.18.4  (313ms)
✔ Installed dplyr 1.2.1  (312ms)
✔ Installed haven 2.5.5  (341ms)
✔ Installed lubridate 1.9.5  (338ms)
✔ Installed readr 2.2.0  (335ms)
✔ Installed readxl 1.4.5  (332ms)
✔ Installed rlang 1.2.0  (327ms)
✔ Installed S7 0.2.2  (315ms)
✔ Installed tidyr 1.3.2  (312ms)
✔ Installed tidyverse 2.0.0  (308ms)
✔ Installed timechange 0.4.0  (301ms)
✔ Installed tzdb 0.5.0  (298ms)
✔ Installed uuid 1.2-2  (291ms)
✔ Installed vctrs 0.7.3  (353ms)
✔ Installed vroom 1.7.1  (78ms)
✔ Installed xml2 1.5.2  (66ms)
✔ Installed yaml 2.3.12  (32ms)
✔ 1 pkg + 95 deps: kept 47, upd 17, dld 17 (15.03 MB) [9.1s]
> install.packages("ggplot2")
Warning: unable to access index for repository https://__token__@solo.packagemanager.posit.co/cran-auth/latest/src/contrib:
  cannot open URL 'https://__token__@solo.packagemanager.posit.co/cran-auth/latest/src/contrib/PACKAGES'
Warning: unable to access index for repository https://__token__@solo.packagemanager.posit.co/cran-auth/latest/bin/macosx/big-sur-arm64/contrib/4.5:
  cannot open URL 'https://__token__@solo.packagemanager.posit.co/cran-auth/latest/bin/macosx/big-sur-arm64/contrib/4.5/PACKAGES'
Warning message:
package ‘ggplot2’ is not available for this version of R

A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
                                                                                                                                                                                                           
% cat ~/.ppm/tokens.toml
[[connection]]
url = "https://solo.packagemanager.posit.co"
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...."
method = "sso"

There are a few small issues I noticed:

1. TOML field names don't match the rest of the ecosystem. pak writes:

[[connection]]
url = "..."
token = "..."
method = "sso"

but both rspm login sso and posit-keyring use [[connections]] (plural), address, and auth_type. As-is, a token pak writes is invisible to the other two tools (and vice versa). The connection, url, and method fields should be updated to match the others.

2. The manual TOML writer drops unknown fields, which corrupts other tools' entries. The write function hand-builds the file emitting only the three fields it knows about, for every entry in the file:

for (conn in existing_data$connection) {
  output_lines <- c(output_lines,
    "[[connection]]",
    paste0("url = \"", conn$url, "\""),
    paste0("token = \"", conn$token, "\""),
    paste0("method = \"", conn$method, "\""),
    "")
}

So if a user runs rspm login sso against a Snowflake-backed PPM (which writes snowflake_connection = "..." per entry) and then runs pak::pkg_install(...) against a different host, pak rewrites the file and the Snowflake field on the other entry is silently gone. pak should be able to add back all fields that exist. We should probably also add support for the optional snowflake_connection field in pak, but I haven't really thought that through yet.

3. File permissions aren't set. rspm and posit-keyring both chmod 0600 on every write (and 0700 on the ~/.ppm dir), but pak doesn't.

4. The "Found credentials for repo ... (SSO)" alert fires once per concurrent download. On a tidyverse install with parallel downloads, I got that line 17 times in a row, once per worker:

✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).
... (15 more times)

We could probably suppress those to have it only appear once in the logs, but not a big deal.

@gaborcsardi
Copy link
Copy Markdown
Member Author

gaborcsardi commented May 12, 2026

Thanks for the feedback!

The meaningful work of this is now happening at r-lib/pkgcache#136
I'll update pak soonish, I think it is mostly ready in pkgcache.

  1. TOML field names don't match the rest of the ecosystem. pak writes:

These are from https://github.com/r-lib/keyring/pull/178/changes#diff-966604c4bb47e72a366ca9a1e1d0e349b763d672f0893cdee30f4db6368e9377R297-R300 So I guess in the meanwhile you have changed this. In any case, we can change the keys, no problem.

  1. The manual TOML writer drops unknown fields,

I fixed this already.

  1. File permissions aren't set.

I fixed this as well.

  1. The "Found credentials for repo ... (SSO)" alert fires once per concurrent download.

Fixed this as well.

gaborcsardi added a commit to r-lib/pkgcache that referenced this pull request May 13, 2026
gaborcsardi added a commit to r-lib/pkgcache that referenced this pull request May 13, 2026
@gaborcsardi
Copy link
Copy Markdown
Member Author

gaborcsardi commented May 13, 2026

Updated the keys in the token file, added some docs, and also improved the user experience:

> Sys.setenv(PACKAGEMANAGER_ADDRESS = "https://solo.packagemanager.posit.co")
> options(repos = c(CRAN  = "https://__token__@solo.packagemanager.posit.co/cran-auth/latest"))
> ppm_sso_login()
── PPM SSO Login ──────────────────────────────────────────────────────────────────────────────
Login at <https://trial-7955023.okta.com/activate?user_code=HKPZJKKG>
and enter code HKPZJKKG when prompted.Authorization successful.
> ppm_sso_status(connect = TRUE)
── PPM SSO Status ───────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/gaborcsardi/.ppm/tokens.toml
Token:       eyJ...s5ig
Valid:       yes
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 14:34:44
Expires at:  2026-05-13 15:34:44
Expired:     no
Expires in:  27m 49.4s
> repo_get()
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest>
(SSO).
# A data frame: 6 × 7
  name          url           type  r_version bioc_version username has_password
* <chr>         <chr>         <chr> <chr>     <chr>        <chr>    <lgl>       
1 CRAN          https://__tocran  *         NA           __tokenTRUE        
2 BioCsoft      https://biocbioc  4.6.0     3.23         NA       NA          
3 BioCann       https://biocbioc  4.6.0     3.23         NA       NA          
4 BioCexp       https://biocbioc  4.6.0     3.23         NA       NA          
5 BioCworkflows https://biocbioc  4.6.0     3.23         NA       NA          
6 BioCbooks     https://biocbioc  4.6.0     3.23         NA       NA          
> repo_ping()
✔ Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest>
(SSO).
Repository summary:                                      source aarch64-apple-darwin23          
CRAN          @ __token__@solo.packagemanager.posit.co     ✔              ✔              (493ms)
BioCsoft      @ bioconductor.org                           ✔              ✔              (71ms )
BioCann       @ bioconductor.org                           ✔              ✔              (126ms)
BioCexp       @ bioconductor.org                           ✔              ✔              (101ms)
BioCworkflows @ bioconductor.org                           ✔              ✔              (176ms)
BioCbooks     @ bioconductor.org                           ✔              ✔              (170ms)
> cache_clean()
> pak::pkg_install("shiny", lib = tempfile())
ℹ Creating library directory: /var/folders/h9/6ct_py4s319fxt88dxn506l00000gp/T//Rtmp3Uq8Oy/file8ca2712c6ca3Loading metadata database ... doneWill install 30 packages.Will download 30 packages with unknown size.
+ base64enc     0.1-6     🔧 ⬇
+ bslib         0.10.0+ cachem        1.1.0     🔧 ⬇
+ cli           3.6.6     🔧 ⬇
+ commonmark    2.0.0     🔧 ⬇
+ digest        0.6.39    🔧 ⬇
+ fastmap       1.2.0     🔧 ⬇
+ fontawesome   0.5.3+ fs            2.1.0     🔧 ⬇
+ glue          1.8.1     🔧 ⬇
+ htmltools     0.5.9     🔧 ⬇
+ httpuv        1.6.17    🔧 ⬇
+ jquerylib     0.1.4+ jsonlite      2.0.0     🔧 ⬇
+ later         1.4.8     🔧 ⬇
+ lifecycle     1.0.5+ magrittr      2.0.5     🔧 ⬇
+ memoise       2.0.1+ mime          0.13      🔧 ⬇
+ otel          0.2.0+ promises      1.5.0+ R6            2.6.1+ rappdirs      0.3.4     🔧 ⬇
+ Rcpp          1.1.1-1.1 🔧 ⬇
+ rlang         1.2.0     🔧 ⬇
+ sass          0.4.10    🔧 ⬇
+ shiny         1.13.0+ sourcetools   0.1.7-2   🔧 ⬇
+ withr         3.0.2+ xtable        1.8-8      ⬇
ℹ Getting 30 pkgs with unknown sizesFound credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).Got base64enc 0.1-6 (aarch64-apple-darwin23) (38.77 kB)                                             
✔ Got cachem 1.1.0 (aarch64-apple-darwin23) (78.06 kB)                                                
✔ Got glue 1.8.1 (aarch64-apple-darwin23) (182.78 kB)                                                 
✔ Got commonmark 2.0.0 (aarch64-apple-darwin23) (141.33 kB)                                           
✔ Got digest 0.6.39 (aarch64-apple-darwin23) (390.11 kB)                                              
✔ Got cli 3.6.6 (aarch64-apple-darwin23) (1.49 MB)                                                    
✔ Got magrittr 2.0.5 (aarch64-apple-darwin23) (234.92 kB)                                             
✔ Got jquerylib 0.1.4 (aarch64-apple-darwin23) (527.01 kB)                                            
✔ Got later 1.4.8 (aarch64-apple-darwin23) (806.50 kB)                                                
✔ Got rappdirs 0.3.4 (aarch64-apple-darwin23) (50.21 kB)                                              
✔ Got R6 2.6.1 (aarch64-apple-darwin23) (88.14 kB)                                                    
✔ Got jsonlite 2.0.0 (aarch64-apple-darwin23) (1.11 MB)                                               
✔ Got sourcetools 0.1.7-2 (aarch64-apple-darwin23) (151.97 kB)                                        
✔ Got withr 3.0.2 (aarch64-apple-darwin23) (225.42 kB)                                                
✔ Got fastmap 1.2.0 (aarch64-apple-darwin23) (223.21 kB)                                              
✔ Got mime 0.13 (aarch64-apple-darwin23) (49.00 kB)                                                   
✔ Got memoise 2.0.1 (aarch64-apple-darwin23) (51.78 kB)                                               
✔ Got lifecycle 1.0.5 (aarch64-apple-darwin23) (133.77 kB)                                            
✔ Got otel 0.2.0 (aarch64-apple-darwin23) (282.02 kB)                                                 
✔ Got htmltools 0.5.9 (aarch64-apple-darwin23) (360.87 kB)                                            
✔ Got fs 2.1.0 (aarch64-apple-darwin23) (461.14 kB)                                                   
✔ Got xtable 1.8-8 (aarch64-apple-darwin23) (753.44 kB)                                               
✔ Got fontawesome 0.5.3 (aarch64-apple-darwin23) (1.40 MB)                                            
✔ Got shiny 1.13.0 (aarch64-apple-darwin23) (4.48 MB)                                                 
✔ Got bslib 0.10.0 (aarch64-apple-darwin23) (6.07 MB)                                                 
✔ Got httpuv 1.6.17 (aarch64-apple-darwin23) (3.17 MB)                                                
✔ Got promises 1.5.0 (aarch64-apple-darwin23) (1.68 MB)                                               
✔ Got rlang 1.2.0 (aarch64-apple-darwin23) (1.94 MB)                                                  
✔ Got sass 0.4.10 (aarch64-apple-darwin23) (2.42 MB)                                                  
✔ Got Rcpp 1.1.1-1.1 (aarch64-apple-darwin23) (3.56 MB)                                               
✔ Downloaded 30 packages (32.55 MB) in 1.7sInstalled base64enc 0.1-6  (144ms)                                                                 
✔ Installed cachem 1.1.0  (141ms)                 
✔ Installed cli 3.6.6  (146ms)                    
✔ Installed commonmark 2.0.0  (164ms)             
✔ Installed digest 0.6.39  (166ms)                
✔ Installed fastmap 1.2.0  (166ms)                
✔ Installed fontawesome 0.5.3  (166ms)            
✔ Installed fs 2.1.0  (167ms)                    
✔ Installed glue 1.8.1  (168ms)                  
✔ Installed htmltools 0.5.9  (168ms)             
✔ Installed bslib 0.10.0  (295ms)                                                                     
✔ Installed httpuv 1.6.17  (211ms)                                                                    
✔ Installed jquerylib 0.1.4  (213ms)                                                                  
✔ Installed jsonlite 2.0.0  (214ms)                                                            
✔ Installed later 1.4.8  (71ms)                                                        
✔ Installed lifecycle 1.0.5  (33ms)                                             
✔ Installed magrittr 2.0.5  (49ms)                                              
✔ Installed memoise 2.0.1  (33ms)                                             
✔ Installed mime 0.13  (30ms)                                             
✔ Installed otel 0.2.0  (31ms)                                             
✔ Installed promises 1.5.0  (33ms)                                         
✔ Installed R6 2.6.1  (31ms)                                             
✔ Installed rappdirs 0.3.4  (48ms)                                         
✔ Installed rlang 1.2.0  (39ms)                                            
✔ Installed sass 0.4.10  (36ms)                                         
✔ Installed Rcpp 1.1.1-1.1  (157ms)                                     
✔ Installed sourcetools 0.1.7-2  (26ms)                                        
✔ Installed shiny 1.13.0  (81ms)                                               
✔ Installed withr 3.0.2  (55ms)                                           
✔ Installed xtable 1.8-8  (23ms)                                          
✔ 1 pkg + 29 deps: added 30, dld 30 (32.55 MB) [4.1s]              

@gaborcsardi
Copy link
Copy Markdown
Member Author

gaborcsardi commented May 13, 2026

Unfortunately, to publish it I'll need to publish pkgcache, which is fine, but I also need to put the ts and tstoml packages on CRAN, which might take longer.

Nevertheless I can merge it, which will make nightly build binaries available at https://pak.r-lib.org/reference/install.html#nightly-builds if that helps.

Copy link
Copy Markdown

@jmwoliver jmwoliver left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, thanks so much for this! I tested it again and everything is working well. I found a few small things, but I'll approve so you can merge whenever.

  • If you set the PACKAGEMANAGER_ADDRESS but have not logged in, it could give a better indicator how to login.
> Sys.setenv(PACKAGEMANAGER_ADDRESS = "https://solo.packagemanager.posit.co")
> options(repos = c(CRAN  = "https://__token__@solo.packagemanager.posit.co/cran-auth/latest"))
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       NA
Valid:       no
Issuer:      NA
Subject:     NA
Audience:    NA
Issued at:   NA
Expires at:  NA
Expired:     ?
Expires in:  -
  • The connect = TRUE setting is a little vague as to what it does, I assume it only affects the Valid field? It could be validate = TRUE or something like that, but not a big deal.
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       eyJ...ObR8
Valid:       yes
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 09:29:45
Expires at:  2026-05-13 10:29:45
Expired:     no
Expires in:  59m 7.2s
> pak::ppm_sso_status()
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       eyJ...ObR8
Valid:       ?
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 09:29:45
Expires at:  2026-05-13 10:29:45
Expired:     no
Expires in:  59m 3.1s
  • Does the token get cached in memory? While testing I tried to delete the connections block in ~/.ppm/tokens.toml, but the token continued to work.
> Sys.setenv(PACKAGEMANAGER_ADDRESS = "https://solo.packagemanager.posit.co")
> options(repos = c(CRAN  = "https://__token__@solo.packagemanager.posit.co/cran-auth/latest"))
> pak::cache_clean()
> pak::pkg_install("shiny", lib = tempfile())
ℹ Creating library directory: /var/folders/1x/w1y7rrb96rddmnxtn89w0frc0000gp/T//RtmpNjk8LR/file163cd4a50b767Loading metadata database ... doneWill install 30 packages.Will download 30 CRAN packages (31.71 MB).
+ base64enc     0.1-6     🔧 ⬇ (38.12 kB)
+ bslib         0.10.0     ⬇ (6.07 MB)
+ cachem        1.1.0     🔧 ⬇ (71.08 kB)
+ cli           3.6.6     🔧 ⬇ (1.47 MB)
+ commonmark    2.0.0     🔧 ⬇ (139.17 kB)
+ digest        0.6.39    🔧 ⬇ (362.19 kB)
+ fastmap       1.2.0     🔧 ⬇ (192.97 kB)
+ fontawesome   0.5.3      ⬇ (1.39 MB)
+ fs            2.1.0     🔧 ⬇ (439.08 kB)
+ glue          1.8.1     🔧 ⬇ (175.14 kB)
+ htmltools     0.5.9     🔧 ⬇ (360.56 kB)
+ httpuv        1.6.17    🔧 ⬇ (2.78 MB)
+ jquerylib     0.1.4      ⬇ (526.50 kB)
+ jsonlite      2.0.0     🔧 ⬇ (1.11 MB)
+ later         1.4.8     🔧 ⬇ (768.65 kB)
+ lifecycle     1.0.5      ⬇ (132.98 kB)
+ magrittr      2.0.5     🔧 ⬇ (231.97 kB)
+ memoise       2.0.1      ⬇ (49.48 kB)
+ mime          0.13      🔧 ⬇ (48.28 kB)
+ otel          0.2.0      ⬇ (280.77 kB)
+ promises      1.5.0      ⬇ (1.68 MB)
+ R6            2.6.1      ⬇ (87.28 kB)
+ rappdirs      0.3.4     🔧 ⬇ (48.79 kB)
+ Rcpp          1.1.1-1.1 🔧 ⬇ (3.36 MB)
+ rlang         1.2.0     🔧 ⬇ (1.90 MB)
+ sass          0.4.10    🔧 ⬇ (2.41 MB)
+ shiny         1.13.0     ⬇ (4.47 MB)
+ sourcetools   0.1.7-2   🔧 ⬇ (135.37 kB)
+ withr         3.0.2      ⬇ (224.91 kB)
+ xtable        1.8-8      ⬇ (754.22 kB)
ℹ Getting 30 pkgs (31.71 MB)
── PPM SSO Login ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Login at <https://trial-7955023.okta.com/activate?user_code=RRGJDMVQ>
and enter code RRGJDMVQ when prompted.Authorization successful.Found credentials for repo <https://__token__@solo.packagemanager.posit.co/cran-auth/latest> (SSO).Got base64enc 0.1-6 (aarch64-apple-darwin20) (38.12 kB)
✔ Got cachem 1.1.0 (aarch64-apple-darwin20) (71.08 kB)
✔ Got commonmark 2.0.0 (aarch64-apple-darwin20) (139.17 kB)
✔ Got digest 0.6.39 (aarch64-apple-darwin20) (362.19 kB)
✔ Got mime 0.13 (aarch64-apple-darwin20) (48.28 kB)
✔ Got htmltools 0.5.9 (aarch64-apple-darwin20) (360.56 kB)
✔ Got jquerylib 0.1.4 (aarch64-apple-darwin20) (526.50 kB)
✔ Got R6 2.6.1 (aarch64-apple-darwin20) (87.28 kB)
✔ Got rappdirs 0.3.4 (aarch64-apple-darwin20) (48.79 kB)
✔ Got sourcetools 0.1.7-2 (aarch64-apple-darwin20) (134.93 kB)
✔ Got withr 3.0.2 (aarch64-apple-darwin20) (224.91 kB)
✔ Got cli 3.6.6 (aarch64-apple-darwin20) (1.47 MB)
✔ Got memoise 2.0.1 (aarch64-apple-darwin20) (49.48 kB)
✔ Got xtable 1.8-8 (aarch64-apple-darwin20) (754.22 kB)
✔ Got fastmap 1.2.0 (aarch64-apple-darwin20) (192.97 kB)
✔ Got fs 2.1.0 (aarch64-apple-darwin20) (439.45 kB)
✔ Got lifecycle 1.0.5 (aarch64-apple-darwin20) (131.51 kB)
✔ Got otel 0.2.0 (aarch64-apple-darwin20) (280.77 kB)
✔ Got promises 1.5.0 (aarch64-apple-darwin20) (1.68 MB)
✔ Got later 1.4.8 (aarch64-apple-darwin20) (768.65 kB)
✔ Got bslib 0.10.0 (aarch64-apple-darwin20) (6.06 MB)
✔ Got httpuv 1.6.17 (aarch64-apple-darwin20) (2.78 MB)
✔ Got jsonlite 2.0.0 (aarch64-apple-darwin20) (1.08 MB)
✔ Got magrittr 2.0.5 (aarch64-apple-darwin20) (231.62 kB)
✔ Got rlang 1.2.0 (aarch64-apple-darwin20) (1.62 MB)
✔ Got fontawesome 0.5.3 (aarch64-apple-darwin20) (1.40 MB)
✔ Got shiny 1.13.0 (aarch64-apple-darwin20) (4.49 MB)
✔ Got sass 0.4.10 (aarch64-apple-darwin20) (2.22 MB)
✔ Got glue 1.8.1 (aarch64-apple-darwin20) (172.25 kB)
✔ Got Rcpp 1.1.1-1.1 (aarch64-apple-darwin20) (3.36 MB)
✔ Downloaded 30 packages (31.22 MB) in 9.6sInstalled base64enc 0.1-6  (187ms)
✔ Installed cachem 1.1.0  (177ms)
✔ Installed cli 3.6.6  (180ms)
✔ Installed commonmark 2.0.0  (179ms)
✔ Installed digest 0.6.39  (180ms)
✔ Installed fastmap 1.2.0  (195ms)
✔ Installed fontawesome 0.5.3  (187ms)
✔ Installed fs 2.1.0  (187ms)
✔ Installed glue 1.8.1  (186ms)
✔ Installed htmltools 0.5.9  (185ms)
✔ Installed httpuv 1.6.17  (185ms)
✔ Installed bslib 0.10.0  (349ms)
✔ Installed jquerylib 0.1.4  (216ms)
✔ Installed jsonlite 2.0.0  (215ms)
✔ Installed later 1.4.8  (85ms)
✔ Installed lifecycle 1.0.5  (41ms)
✔ Installed magrittr 2.0.5  (38ms)
✔ Installed memoise 2.0.1  (38ms)
✔ Installed mime 0.13  (38ms)
✔ Installed otel 0.2.0  (37ms)
✔ Installed promises 1.5.0  (38ms)
✔ Installed R6 2.6.1  (40ms)
✔ Installed rappdirs 0.3.4  (60ms)
✔ Installed rlang 1.2.0  (24ms)
✔ Installed sass 0.4.10  (32ms)
✔ Installed Rcpp 1.1.1-1.1  (135ms)
✔ Installed sourcetools 0.1.7-2  (26ms)
✔ Installed shiny 1.13.0  (84ms)
✔ Installed withr 3.0.2  (40ms)
✔ Installed xtable 1.8-8  (24ms)
✔ 1 pkg + 29 deps: added 30, dld 30 (31.22 MB) [12.5s]
Warning message:
In normalizePath(lib) :
  path[1]="/var/folders/1x/w1y7rrb96rddmnxtn89w0frc0000gp/T//RtmpNjk8LR/file163cd4a50b767": No such file or directory
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       eyJ...7M8g
Valid:       yes
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 09:57:51
Expires at:  2026-05-13 10:57:51
Expired:     no
Expires in:  59m 39.1s

In another terminal, delete the [[connections]] that pak created. Back in the same R session:

> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       eyJ...7M8g
Valid:       yes
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 09:57:51
Expires at:  2026-05-13 10:57:51
Expired:     no
Expires in:  59m 16.9s
> pak::ppm_sso_login()
── PPM SSO Login ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Login at <https://trial-7955023.okta.com/activate?user_code=JXQJRMFR>
and enter code JXQJRMFR when prompted.Authorization successful.
[1] "eyJh...nbSb0"
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       eyJ...7M8g
Valid:       yes
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 09:57:51
Expires at:  2026-05-13 10:57:51
Expired:     no
Expires in:  58m 34.7s

Notice how the token returned still gets returned by ppm_sso_status() after deleting the entry in ~/.ppm/tokens.toml. It also doesn't get updated after running ppm_sso_login() and getting a fresh token.

@gaborcsardi
Copy link
Copy Markdown
Member Author

  • Does the token get cached in memory? While testing I tried to delete the connections block in ~/.ppm/tokens.toml, but the token continued to work.
    [...]
    It also doesn't get updated after running ppm_sso_login() and getting a fresh token.

Yes, it is cached in memory. If you want to remove the token from the cache and the disk, call ppm_sso_logout().

@jmwoliver
Copy link
Copy Markdown

If you want to remove the token from the cache and the disk, call ppm_sso_logout().

Ah makes sense, no one should manually update ~/.ppm/tokens.toml anyways. It looks like running pak::ppm_sso_login() twice works as expected if you don't manually delete the [[connections]] entry in ~/.ppm/tokens.toml:

> Sys.setenv(PACKAGEMANAGER_ADDRESS = "https://solo.packagemanager.posit.co")
> options(repos = c(CRAN  = "https://__token__@solo.packagemanager.posit.co/cran-auth/latest"))
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       NA
Valid:       no
Issuer:      NA
Subject:     NA
Audience:    NA
Issued at:   NA
Expires at:  NA
Expired:     ?
Expires in:  -
> pak::ppm_sso_login()
── PPM SSO Login ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Login at <https://trial-7955023.okta.com/activate?user_code=NHFBJLQR>
and enter code NHFBJLQR when prompted.Authorization successful.
[1] "eyJh...0QpRnEU"
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       eyJ...RnEU
Valid:       yes
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 10:15:41
Expires at:  2026-05-13 11:15:41
Expired:     no
Expires in:  59m 54s
> pak::ppm_sso_login()
── PPM SSO Login ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Login at <https://trial-7955023.okta.com/activate?user_code=KLGMLTJJ>
and enter code KLGMLTJJ when prompted.Authorization successful.
[1] "eyJhbGc...Rpvo"
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       eyJ...Rpvo
Valid:       yes
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 10:15:58
Expires at:  2026-05-13 11:15:58
Expired:     no
Expires in:  59m 56.3s

@jmwoliver
Copy link
Copy Markdown

I think I found a bug. If you logout, logging back in doesn't update the ~/.ppm/tokens.toml file again:

> Sys.setenv(PACKAGEMANAGER_ADDRESS = "https://solo.packagemanager.posit.co")
> options(repos = c(CRAN  = "https://__token__@solo.packagemanager.posit.co/cran-auth/latest"))> options(repos = c(CRAN  = "https://__token__@solo.packagemanager.posit.co/cran-auth/latest"))
> pak::ppm_sso_login()
── PPM SSO Login ───────────────────────────────────────────────────────────────────────────────────
Login at <https://trial-7955023.okta.com/activate?user_code=CWQPFKNT>
and enter code CWQPFKNT when prompted.Authorization successful.
[1] "eyJ...sSuw"
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ──────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       eyJ...sSuw
Valid:       yes
Issuer:      packagemanager
Subject:     rspm@posit.co
Audience:    packagemanager
Issued at:   2026-05-13 13:34:21
Expires at:  2026-05-13 14:34:21
Expired:     no
Expires in:  59m 51.1s
> pak::ppm_sso_logout()
NULL
> pak::ppm_sso_login()
── PPM SSO Login ───────────────────────────────────────────────────────────────────────────────────
Login at <https://trial-7955023.okta.com/activate?user_code=HWLNDPSM>
and enter code HWLNDPSM when prompted.Authorization successful.
[1] "eyJ...vvo"
> pak::ppm_sso_status(connect = TRUE)
── PPM SSO Status ──────────────────────────────────────────────────────────────────────────────────
PPM URL:     https://solo.packagemanager.posit.co
Token file:  /Users/jacobwoliver/.ppm/tokens.toml
Token:       NA
Valid:       no
Issuer:      NA
Subject:     NA
Audience:    NA
Issued at:   NA
Expires at:  NA
Expired:     ?
Expires in:  -

The ~/.ppm/tokens.toml file remains empty after the logout:

% cat ~/.ppm/tokens.toml
%

@gaborcsardi
Copy link
Copy Markdown
Member Author

gaborcsardi commented May 13, 2026

I think this is fixed already, just pushed my local tree: r-lib/pkgcache@d9a5ad9 (#136) and f3e750e (this PR).

So that it works
- on a text man page,
- on a HTML man page,
- in pkgdown.
Do not refer to `pkgcache::ppm_sso_*()` functions.
To fix R CMD check issues.
@gaborcsardi gaborcsardi merged commit 3f1b0aa into main May 14, 2026
@gaborcsardi gaborcsardi deleted the feature/ppm-sso branch May 14, 2026 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants